Chris Chevalier
Chris Chevalier

Reputation: 196

To edit a many to many relationship in Entity Framework, why must I clear the collection first?

I have the following code for editing the departments a user is in. For some reason, method1 causes EF to try and insert the relationship again (and causing a primary key error), where method2 succeeds.

Why does the code of method1 not know that by reassigning the value, I only want the new collection of departments? Is method2 the preferred method to update values? I haven't had to do it this way with one to many relationships.

public class User
{
    public string name { get; set; }
    public virtual List<Department> Departments { get; set; }
}

public class Department
{
    public string name { get; set; }
    public virtual List<User> Users { get; set; }
}

public void Method1(list<Department> departments, string userId)
{
    var user = DbContext.Users.FirstOrDefault(u=> u.Id == userId);
    user.departments = departments;
    db.SaveChanges()
}

public void Method2(list<Department> departments, string userId) 
{
    var user = DbContext.Users.FirstOrDefault(u=> u.Id == userId);
    user.departments.clear();
    user.departments = departments;
    db.SaveChanges()
}

Upvotes: 2

Views: 704

Answers (1)

Slava Utesinov
Slava Utesinov

Reputation: 13498

Below on departments, I will mean Users2Departments table.

Probably, it happened because, when you wrote user.departments.clear(); you loaded all related departments(via LazyLoading), so they become trackable by EF and were successfully marked as Deleted(after clear() call). And then new departments were assigned to user, i.e. marked as Added. All is correct.

But, if you just perform only assigning: user.departments = departments, EF will not know or not care, that there are existed departments and it should delete them, because, at least, they are not tracked, because they not loaded, since user.departments literal is located at LeftHandSide(user.departments.clear() is RightHandSide). Moreover Users2Departments table is implicit table. So EF only inserts new departments without deletion of previous ones, so exception will may occur.

Upvotes: 2

Related Questions