想象一下这个数据库模型:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Firstname { get; set; }
public ICollection<Role> Roles { get; set; }
}
public class Role
{
public int Id { get; set; }
public string RoleType { get; set; }
public ICollection<User> Users { get; set; }
}
有一个中间表看起来像这样(不作为POCO存在):
用户角色用户ID角色ID
然后我决定删除一个角色,这意味着这个角色在中间表中的所有关系也应该被删除。
无论我尝试什么,我都会收到以下错误消息:
DELETE语句与REFERENCE约束"FK_UserRole_Role"冲突。冲突发生在数据库"dbname"、表"dbo.UserRole"、列"RoleId"中
或者这个错误消息:
无法删除该对象,因为在ObjectStateManager中找不到该对象
第一条错误消息来自这次尝试:
_dataContext.Entry(role).State = EntityState.Deleted;
_dataContext.SaveChanges();
这个负责第二条错误消息:
_dataContext.Circuit.Remove(role);
_dataContext.SaveChanges();
我还做了一些其他的尝试,但我不记得了,因为我从今天早上(GMT+2)开始一直在努力让它发挥作用。
有人能给我指正确的方向吗?
在调用Remove
:之前,可以先将role
附加到上下文,使第二个异常消失
_dataContext.Roles.Attach(role);
_dataContext.Roles.Remove(role);
_dataContext.SaveChanges();
但是,您很可能也会得到此代码的第一个异常,因为真正的问题是,您显然没有在数据库中分别为从UserRoles
表到Users
表和Roles
表的两个关系启用级联删除。
您可以在SQLServerManagementStudio中将这两种关系的删除规则设置为"级联",例如此处所示。在此之后,删除角色还应删除UserRoles
链接表中的条目。
编辑
加载相关用户时,您也可以在不启用级联删除的情况下成功删除角色:
var role = _dataContext.Roles.Include(r => r.Users)
.Single(r => r.Id == someRoleId);
_dataContext.Roles.Remove(role);
// _dataContext.Entry(role).State = EntityState.Deleted; will work as well
_dataContext.SaveChanges();
不同之处在于,当相关用户与角色一起附加到上下文时,EF将为UserRoles
链接表中的每一行发送一个单独的DELETE语句,然后为角色发送一个DELETE语句,这样它就可以在不违反FK约束的情况下工作。