简体   繁体   中英

Entity framework - how to remove data from junction table

my problem is following - I have 2 tables (users, roles) with relation many-to-many. When I want to add new role for user, everything is OK, but I am not able to remove role from user.

List<Role> roles = new List<Role>(); 
roles.Add(role1); roles.Add(role3); 
User user = db.users.Find(1); 
user.roles = roles; 
db.Entry(user).State = EntityState.Modified; 
db.SaveChanges();

As I mentioned above, this code inserts new roles (1,3), but it does not delete role 2 (if exists). I have no clue how to delete record from this junction table, can you help me please? I know, that when I delete object from one table, all data related with this object are deleted from junction table, but i do not want to delete -> add object since it is related with another tables.

Here is another solution, you firstly have to load the related roles of the user before replacing the whole roles with your new list, like this:

User user = db.users.Include<User, ICollection<Role>>(u=>u.roles)
                    .FirstOrDefault(u=>u.ID == 1);
if(user != null){
    user.roles = roles;
    db.SaveChanges();
}

I supposed your roles navigation property has type of ICollection<Role> and the user's key property is ID , you can read more about using Include extension method (declared in QueryableExtensions .

You have to remove role2 from user.

List<Role> roles = new List<Role>(); 
roles.Add(role1); roles.Add(role3); 
User user = db.users.Find(1); 
user.roles.Remove(role2);
user.roles = roles;  
db.SaveChanges();

First you need to include roles when loading your user:

var user = db.users
    .Include(x=>x.Roles)
    .Single(x=>x.Id == 1);

Then you need to identify Role to remove:

var roleToRemove = user.roles.Single(x => x.Id == 1);

And Finally you remove the role and save changes

user.Roles.Remove(roleToRemove);
db.SaveChanges();

For DbContext to be able to track changes you have to let it load collections first then just by modifying that collection DbContext will know how to update DB.

PS. You can use lazy load option if collection is large and you don't want to load all linked elements.

The problem is EF doesn't know you want to delete the older roles. When you set the Roles navigation property with the new list, you are only telling to EF that you want to add those new two roles, but you are not changing the state of the older roles to Deleted . There are two options to achieve what you need:

  • Changing the state to Deleted :

     User user = db.users.Find(1); // change the state to Deleted. foreach(var r in user.Roles) db.Entry(r).State = System.Data.Entity.EntityState.Deleted; // Add the new roles user.Roles.AddRange(roles); 
  • Using the Remove method:

     User user = db.users.Find(1); // delete older roles foreach(var r in user.Roles.ToList()) user.Roles.Remove(r); // Add the new roles user.Roles.AddRange(roles); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM