EF: Updating entity with added, removed or unchanged child entities (many to many relationship)

Viewed 1027

It's the first time I am using EF in an asp.net mvc app. For the last two days I am reading similar questions and examples, but up to this point I have not understand exactly what I have to do.

I have two entities with many to many relationship.

Model:

[Table("Unit")]
public class UnitEntity
{
    [Required]
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public UnitType Type { get; set; }

    [StringLength(255)]
    public string Title { get; set; }

    ///some other properties

    public virtual ICollection<UserEntity> Users { get; set; }
}

[Table("User")]
public class UserEntity
{
    [StringLength(255)]
    public string Id { get; set; }

    [Required]
    public string UserName { get; set; }

    [Required]
    public string Email { get; set; }


    public int Status { get; set; }

    // some other properties

    public virtual ICollection<UnitEntity> DepartmentUnits { get; set; }
}

And in my dbcontext:

public virtual DbSet<UnitEntity>  Units { get; set; }
public virtual DbSet<UserEntity> Users { get; set; }

 modelBuilder.Entity<UserEntity>()
           .HasMany(e => e.DepartmentUnits)
           .WithMany(e => e.Users)
           .Map(m => m.ToTable("UserDepartments").MapLeftKey("UserId").MapRightKey("DepartmentId"));

The list of DepartmentUnits for each user are updated in a view using a Multiselect List and passed to controller.

Controller method:

    [HttpPost]
    public ActionResult UpdateUser(ExternalUserDTO userdata)
    {
        //list of UnitDepartments from the view
        var userDepartments = new List<UnitEntity>();
        foreach (var unitid in userdata.DepartmentIds)
        {
            userDepartments.Add(manager.GetUnit(unitid));
        }


        //create new user with data to update 
        UserEntity userentity = new UserEntity()
        {
            Id = userdata.Id,
            DepartmentUnits = userDepartments,
            Status = userdata.Status

        };


        userManager.UpdateUser(userentity);

        return new JsonResult { Data = new { Success = false } };
    }

And in UserManager class:

public void UpdateUser(UserEntity entity)
    {
        var updentity = this.dataContext.Users.Find(entity.Id);

        if (updentity == null)
            throw new NullReferenceException("User not found");


        updentity.Status = entity.Status;

        var newUnitIds = entity.DepartmentUnits.Select(u => u.Id);
        var existingUnitIds = updentity.DepartmentUnits.Select(u => u.Id);

        updentity.DepartmentUnits.Where(u => !newUnitIds.Contains(u.Id)).ToList().ForEach(d => updentity.DepartmentUnits.Remove(d));
        entity.DepartmentUnits.Where(u => newUnitIds.Except(existingUnitIds).Contains(u.Id)).ToList().ForEach(d => updentity.DepartmentUnits.Add(d));


        this.dataContext.Entry(updentity).State =  EntityState.Modified;


        foreach (var deptentity in updentity.DepartmentUnits)
        {
            if(newUnitIds.Contains(deptentity.Id))
            {
                this.dataContext.Entry(deptentity).State = EntityState.Added;
            }
            if(existingUnitIds.Contains(deptentity.Id))
            {
                this.dataContext.Entry(deptentity).State = EntityState.Unchanged;
            }
        }


        try
        {
            this.dataContext.SaveChanges();

        }
        catch (Exception)
        {
            throw new Exception("Update problem");
        }

    }

I need to update my UserDepartments table (see model builder above), in order to delete removed, add new and retain existing DepartmentUnits for the specific user. The above is not working, I am lost and I appreciate any help.

2 Answers
Related