更新 Entity Framework 中的多对多关系

Updating many to many relationships in Entity Framework

我能够成功创建用户。我现在正在尝试在创建过程中为用户分配一些角色。

我在 Entity Framework 中使用数据库优先的方法。我试过遵循一些教程并查看其他人的解决方案,但似乎无法正常工作。

我有 3 个表:UserRoleUserRole(包含 UserIdRoleId)。

UserRole之间的关系是多对多。

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();

我终于想出了解决办法。

  1. 多对多 table UserRole 没有任何主键。因此,我添加了一个与 UserId 和 RoleId 一致的 PK。

  2. 我删除了角色列表,因为我不需要它

    [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) 之后一切正常。