我确定这个问题之前已经被问过,所以我提前道歉,但我不确定在我的搜索中包含正确的关键字......
当对象的一个属性是断开连接的环境(如网站)中其他属性的集合时,我无法理解更新(甚至插入)对象的正确模式。我的问题与 Web 应用程序仅返回 id 集合而不是完整对象的想法有关。我认为解释这一点的最好方法是使用代码片段。
给定以下对象
Public Class User
Public Property UserId As Integer
Public Property Username As String
Public Property Roles As ICollection(Of Role)
End Class
Public Class Role
Public Property RoleId As Integer
Public Property RoleName As String
Public Property Users As ICollection(OF User)
End Class
Public Class EFDbContext
Inherits Entity.DbContext
Public Property Users As Entity.DbSet(Of User)
Public Property Roles As Entity.DbSet(Of Role)
End Class
使用 3 个表创建一个数据库 - 用户、角色和角色用户。
我知道我可以轻松地做到以下几点
Dim db = New EFDbContext()
Dim r1 = New Role() With { .RoleName = "User" }
Dim r2 = New Role() With { .RoleName = "Admin" }
db.Roles.Add(r1)
db.Roles.Add(r2)
Dim u1 = New User() With { .UserName = "test1", .Roles = New List(Of Role) }
u1.Roles.Add(r1)
db.Users.Add(u1)
db.SaveChanges()
它会将两个新角色保存到数据库中(分别为它们的 RoleId 值 1 和 2)、一个新用户(给它一个 UserId 值 1)和一个具有 RoleId 1 和 UserId 1 的新 Role-User 条目。
然而,在处理像网站这样的断开连接的场景时,大多数人都会有一个视图模型来表示来自用户的输入,然后将其映射回实体。此外,对于表示角色的值,返回的数据很可能只包含表示角色的唯一键。例如,
Public Class UpdatedUserViewModel
Public Property UserId As Integer
Public Property Username As String
Public Property RoleIds As ICollection(Of Integer)
End Class
...
...
Dim userEntity = db.Users.Find(user.Values.UserId)
AutoMapper.Mapper.Map(userValues, userEntity)
因此,虽然 userEntity.Roles 集合可能包含单个项目,但映射器可能只是添加了类似的条目
ForMember(Function(u) u.Roles, Sub(m) m.MapFrom(Function(su) su.RoleIds.Select(Function(r) New Role() With {.RoleId = r})))
现在我们遇到了问题,当SaveChanges()
调用该方法时,EF 会抛出一个验证错误,因为 .RoleName 属性是 Nothing。
这种情况如何处理?我们是否应该手动遍历角色并从数据库中获取每个角色?我们可以不使用绘图工具吗?我是否为“缺失”属性提供虚假值,然后遍历并将它们标记为未更改?
我知道这很长,但我认为演练会有所帮助......
谢谢。