更新 Entity Framework 中的多对多关系
Updating many to many relationships in Entity Framework
我能够成功创建用户。我现在正在尝试在创建过程中为用户分配一些角色。
我在 Entity Framework 中使用数据库优先的方法。我试过遵循一些教程并查看其他人的解决方案,但似乎无法正常工作。
我有 3 个表:User
、Role
和 UserRole
(包含 UserId
和 RoleId
)。
User
和Role
之间的关系是多对多。
Entity Diagram Showing Relationships
The Create view, which contains checkboxes
数据库上下文 class:
public partial class MyDBEntities : DbContext
{
public MyDBEntities() : base("name=MyDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Role> Roles { get; set; }
}
User.cs:
public partial class User
{
public User()
{
this.Roles = new HashSet<Role>();
}
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string Password_hash { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
Role.cs:
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
[HttpGet] 创建():
public ActionResult Create()
{
return View(new UserCreateVM
{
Roles = db.Roles.Select(x => new RoleCheckboxVM
{
Id = x.Id,
Name = x.Name,
IsChecked = false
}).ToList()
});
}
[HttpPost] 创建():
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserCreateVM vm)
{
User user = new User();
var selectedRoles = new List<Role>();
foreach (var r in db.Roles) // we query all the roles in the database
{
var checkbox = vm.Roles.Single(x => x.Id == r.Id);
checkbox.Name = r.Name; //updates the name on all our checkboxes
if (checkbox.IsChecked) //if checkbox is checked
{
selectedRoles.Add(r); //then we add the role to our selectedRoles
}
}
IList<Role> rolesList = user.Roles.ToList();
foreach (var toAdd in selectedRoles.Where(x => !rolesList.Contains(x))) //if roles is not already added
{
rolesList.Add(toAdd); //then we add them to the user roles
}
if (ModelState.IsValid)
{
//We update the data on the object
user.Username = vm.Username;
user.Email = vm.Email;
user.SetPassword(vm.Password_hash); //we hash the password
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
我看不出你什么时候给 user.roles 分配了角色,正如我所见,你正在将 user.roles 分配给 rolesList,而不是将 rolesList 分配给 user.roles。
我就是这样做的。
User user = new User()
{
Roles = db.Roles.Where(r => vm.Roles.Any(x => x.IsChecked && r.Id = x.Id)).ToList(),
Username = vm.Username,
Email = vm.Email
};
user.SetPassword(vm.Password_hash); //we hash the password
db.Users.Add(user);
db.SaveChanges();
我终于想出了解决办法。
多对多 table UserRole 没有任何主键。因此,我添加了一个与 UserId 和 RoleId 一致的 PK。
我删除了角色列表,因为我不需要它
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserCreateVM vm)
{
User user = new User();
var selectedRoles = new List<Role>();
foreach (var r in db.Roles) // we query all the roles in the database
{
var checkbox = vm.Roles.Single(x => x.Id == r.Id);
checkbox.Name = r.Name; //updates the name on all our checkboxes
if (checkbox.IsChecked) //if checkbox is checked
{
selectedRoles.Add(r); //then we add the role to our selectedRoles
}
}
foreach (var r in selectedRoles.Where(x => !user.Roles.Contains(x))) //if roles is not already added
{
user.Roles.Add(r); //then we add them to the user roles
}
if (ModelState.IsValid)
{
//We update the data on the object
user.Username = vm.Username;
user.Email = vm.Email;
user.SetPassword(vm.Password_hash); //we hash the password
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
然后在更新数据库 table 和数据库模型 (edmx) 之后一切正常。
我能够成功创建用户。我现在正在尝试在创建过程中为用户分配一些角色。
我在 Entity Framework 中使用数据库优先的方法。我试过遵循一些教程并查看其他人的解决方案,但似乎无法正常工作。
我有 3 个表:User
、Role
和 UserRole
(包含 UserId
和 RoleId
)。
User
和Role
之间的关系是多对多。
Entity Diagram Showing Relationships
The Create view, which contains checkboxes
数据库上下文 class:
public partial class MyDBEntities : DbContext
{
public MyDBEntities() : base("name=MyDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Role> Roles { get; set; }
}
User.cs:
public partial class User
{
public User()
{
this.Roles = new HashSet<Role>();
}
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string Password_hash { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
Role.cs:
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
[HttpGet] 创建():
public ActionResult Create()
{
return View(new UserCreateVM
{
Roles = db.Roles.Select(x => new RoleCheckboxVM
{
Id = x.Id,
Name = x.Name,
IsChecked = false
}).ToList()
});
}
[HttpPost] 创建():
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserCreateVM vm)
{
User user = new User();
var selectedRoles = new List<Role>();
foreach (var r in db.Roles) // we query all the roles in the database
{
var checkbox = vm.Roles.Single(x => x.Id == r.Id);
checkbox.Name = r.Name; //updates the name on all our checkboxes
if (checkbox.IsChecked) //if checkbox is checked
{
selectedRoles.Add(r); //then we add the role to our selectedRoles
}
}
IList<Role> rolesList = user.Roles.ToList();
foreach (var toAdd in selectedRoles.Where(x => !rolesList.Contains(x))) //if roles is not already added
{
rolesList.Add(toAdd); //then we add them to the user roles
}
if (ModelState.IsValid)
{
//We update the data on the object
user.Username = vm.Username;
user.Email = vm.Email;
user.SetPassword(vm.Password_hash); //we hash the password
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vm);
}
我看不出你什么时候给 user.roles 分配了角色,正如我所见,你正在将 user.roles 分配给 rolesList,而不是将 rolesList 分配给 user.roles。 我就是这样做的。
User user = new User()
{
Roles = db.Roles.Where(r => vm.Roles.Any(x => x.IsChecked && r.Id = x.Id)).ToList(),
Username = vm.Username,
Email = vm.Email
};
user.SetPassword(vm.Password_hash); //we hash the password
db.Users.Add(user);
db.SaveChanges();
我终于想出了解决办法。
多对多 table UserRole 没有任何主键。因此,我添加了一个与 UserId 和 RoleId 一致的 PK。
我删除了角色列表,因为我不需要它
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(UserCreateVM vm) { User user = new User(); var selectedRoles = new List<Role>(); foreach (var r in db.Roles) // we query all the roles in the database { var checkbox = vm.Roles.Single(x => x.Id == r.Id); checkbox.Name = r.Name; //updates the name on all our checkboxes if (checkbox.IsChecked) //if checkbox is checked { selectedRoles.Add(r); //then we add the role to our selectedRoles } } foreach (var r in selectedRoles.Where(x => !user.Roles.Contains(x))) //if roles is not already added { user.Roles.Add(r); //then we add them to the user roles } if (ModelState.IsValid) { //We update the data on the object user.Username = vm.Username; user.Email = vm.Email; user.SetPassword(vm.Password_hash); //we hash the password db.Users.Add(user); db.SaveChanges(); return RedirectToAction("Index"); } return View(vm); }
然后在更新数据库 table 和数据库模型 (edmx) 之后一切正常。