我正在尝试更新实体的集合导航属性,但我很确定我不会以正确的方式进行更新。在我的应用程序中,我创建了一个用户和角色模型,因为一个用户可以属于多个角色,角色可以有很多用户,我就这样建模了
为简报省略了一些字段的用户:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public virtual ICollection<UserRole> UserHasRoles { get; set; }
}
public class Role
{
public int Id { get; set; }
public string UserRole { get; set; }
public virtual ICollection<UserRole> UserHasRoles { get; set; }
}
public class UserRole
{
public int Id { get; set; }
public int UserId { get; set; }
public int RoleId { get; set; }
public User User { get; set; }
public Role Role { get; set; }
}
我制作了一个我给视图的视图模型,以便您可以为用户选择新角色:
public class UserWithRoleViewModel
{
public User User { get; set; }
public List<Role> Roles { get; set; }
public List<int> RoleIds { get; set; }
}
在我的控制器的[HttpPost]操作方法中收到视图模型后,我将其传递到我的存储库并尝试使用所选角色更新用户:
public void SaveChangesToUser(UserWithRoleViewModel model)
{
model.User.UserHasRoles = new List<UserRole>();
foreach (var id in model.RoleIds)
{
model.User.UserHasRoles.Add(new UserRole { UserId = model.User.Id, RoleId = id });
}
_context.Entry(model.User).State = EntityState.Modified;
_context.SaveChanges();
}
我尝试清除导航属性中的旧值并插入新值,但它不起作用。更新其他用户属性可以正常工作,但不能导航属性。所以我的问题是,为什么这不起作用,我甚至试图以正确的方式做到这一点?
答案 0 :(得分:0)
其实我把它拿回来,我看你在做什么,试试下面的代码
public void SaveChangesToUser(UserWithRoleViewModel model)
{
model.User.UserHasRoles = new List<UserRole>();
_context.Entry(model.User).State = EntityState.Modified;
foreach (var id in model.RoleIds)
{
var userRole = new UserRole { UserId = model.User.Id, RoleId = id };
model.User.UserHasRoles.Add(userRole);
_context.Entry(userRole).State = EntityState.Added;
}
_context.SaveChanges();
}
我认为你必须设定所有孩子的状态。
另一个注意事项,我同意@Simon,你不需要UserRole对象,你可以只映射到db中的关联表,只在用户中有ICollection<Role>
,在角色中只有ICollection<User>
。
HasMany(c => c.Users).WithMany(c => c.Roles).Map(r =>
{
r.MapLeftKey("RoleId");
r.MapRightKey("UserId");
r.ToTable("RoleUser");
});
答案 1 :(得分:0)
对于实体框架中的多对多关系,您需要使用流畅的API并声明您的关系。 首先,关联类不应该拥有它自己的主键。
public class UserRole
{
public int UserId { get; set; }
public int RoleId { get; set; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
}
删除UserRole中的Id,UserId和RoleId将组成它的主要内容。既然模型设计得当,我们需要为关系创建模型构建器:
在您的databasecontext类中:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<UserRole>()
.HasKey(cp => new { cp.UserId, cp.RoleId })
.Map(q=>q.ToTable("UserRole")); //your database table name
modelBuilder.Entity<User>()
.Map(q =>q.ToTable("User"))
.HasMany(c => c.UserRole)
.WithRequired()
.HasForeignKey(cp => cp.UserId) //points on the UserId in UserRole table
.WillCascadeOnDelete(); //should handle cascade deletes
modelBuilder.Entity<Role>()
.Map(q =>q.ToTable("Role"))
.HasMany(c => c.UserRole)
.WithRequired()
.HasForeignKey(cp => cp.RoleId)
.WillCascadeOnDelete();
}
确保您的映射使用正确的表名。请注意,lambda中使用的名称是完全随机的,可能会根据您自己的需要进行更改。