实体框架-如何从连接表中删除数据

本文关键字:删除 数据 连接 框架 实体 | 更新日期: 2023-09-27 18:06:55

我的问题是以下-我有2个表(用户,角色)与关系多对多。当我想为用户添加新角色时,一切正常,但是我无法从用户中删除角色。

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

如上所述,这段代码插入了新的角色(1,3),但没有删除角色2(如果存在的话)。我不知道如何从这个结表中删除记录,你能帮我吗?我知道,当我从一个表中删除对象时,与该对象相关的所有数据都从连接表中删除,但我不想删除->添加对象,因为它与另一个表相关。

实体框架-如何从连接表中删除数据

这是另一种解决方案,在用新列表替换整个角色之前,您首先必须加载用户的相关角色,如下所示:

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

我假设你的roles导航属性类型为ICollection<Role>,用户的关键属性为ID,你可以阅读更多关于使用Include扩展方法(在QueryableExtensions中声明)。

你必须从用户中删除role2。

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

首先,您需要在加载用户时包含角色:

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

然后您需要确定要删除的角色:

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

最后删除角色并保存更改

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

为了让DbContext能够跟踪更改,你必须让它首先加载集合,然后通过修改该集合,DbContext将知道如何更新DB。

p。你可以使用延迟加载选项,如果集合很大,你不想加载所有链接的元素。

问题是EF不知道您想要删除旧的角色。当您用新列表设置Roles导航属性时,您只是告诉EF您想要添加这两个新角色,但是您没有将旧角色的状态更改为Deleted。有两个选项可以实现您的需求:

  • 将状态更改为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); 
    
  • 使用Remove方法:

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