Обновление многих для многих отношений в Entity Framework - PullRequest
0 голосов
/ 27 июня 2018

Я могу успешно создать пользователя. Сейчас я пытаюсь назначить пользователю несколько ролей в процессе создания.

Я использую подход, основанный на базе данных, с Entity Framework. Я пытался следовать некоторым учебникам и смотреть на решения других людей, но не могу заставить его работать.

У меня есть 3 таблицы: User, Role и UserRole (содержит UserId и RoleId).

Отношения между User и Role многие-ко-многим.

Диаграмма сущностей, показывающая отношения

Представление «Создать», содержащее флажки

Класс базы данных контекста:

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] Create ():

public ActionResult Create()
{
        return View(new UserCreateVM
        {
            Roles = db.Roles.Select(x => new RoleCheckboxVM
            {
                Id = x.Id,
                Name = x.Name,
                IsChecked = false
            }).ToList()
        });
    }

[HttpPost] Create ():

[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);
    }

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Я наконец понял, как это решить.

  1. У таблицы UserRole «многие ко многим» не было первичного ключа. Поэтому я добавил PK, совместимый как UserId и RoleId.

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

Затем после обновления таблицы базы данных и модели базы данных (edmx) все работало нормально.

0 голосов
/ 27 июня 2018

Я не могу видеть, когда вы назначали роли для user.roles, как я вижу, вы назначаете user.roles для roleList вместо назначения roleList для 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();
...