删除可选的一对多不会将外键设置为空
Deleting Optional 1-to-Many Does Not Set Foreign Key to Null
我有两个实体,它们有一个可选的一对多关系定义和配置如下:
public class A
{
// ...
public int? BId { get; set; }
public B B { get; set; }
}
public class B
{
// ...
public virtual ICollection<A> As { get; set; }
}
public class AConfiguration : EntityTypeConfiguration<A>
{
public A()
{
// ...
HasOptional(r => r.B).WithMany(r => r.As).HasForeignKey(r => r.BId);
}
}
当删除类型 B 的实体时,我希望所有具有指向要删除的 B 实体的外键的 A 类型实体将该 BId 外键设置为 null
。删除操作定义如下:
public void DeleteB(int bId)
{
var entity = _context.Bs.Single(b => b.Id == bId);
_context.Bs.Remove(entity);
_context.SaveChanges();
}
然而,不会发生这种情况。类型 B 的实体已成功删除,但 A 实体上的 BId 仍然是非空的,任何其他对 .SaveChanges() 的调用都会抛出异常,因为这些 BId 引用的行不再存在。
如何删除 B 实体,从而使 BId 属性无效,而无需在删除操作期间手动遍历集合?
如果当前关联的实体已经加载到上下文中,外键只会自动设置为空。换句话说,当删除 b
时,关联的 A
类型的集合只会将它们的 BId
属性 设置为空,如果 A
类型的那些实体已经加载到上下文中。否则,EF 不会知道它们的存在(除非 EF 提供程序自动生成 SQL 将这些外键设置为空...在 SQL 服务器情况下它不会)。
一个选择是执行此操作(如果您不介意加载所有这些实体):
public void DeleteB(int bId)
{
var entity = _context.Bs.Single(b => b.Id == bId);
_context.Entry(entity).Collection(b => b.As).Load();
_context.Bs.Remove(entity);
_context.SaveChanges();
}
另一种选择是编写您自己的 SQL 声明并 运行 声明。
我有两个实体,它们有一个可选的一对多关系定义和配置如下:
public class A
{
// ...
public int? BId { get; set; }
public B B { get; set; }
}
public class B
{
// ...
public virtual ICollection<A> As { get; set; }
}
public class AConfiguration : EntityTypeConfiguration<A>
{
public A()
{
// ...
HasOptional(r => r.B).WithMany(r => r.As).HasForeignKey(r => r.BId);
}
}
当删除类型 B 的实体时,我希望所有具有指向要删除的 B 实体的外键的 A 类型实体将该 BId 外键设置为 null
。删除操作定义如下:
public void DeleteB(int bId)
{
var entity = _context.Bs.Single(b => b.Id == bId);
_context.Bs.Remove(entity);
_context.SaveChanges();
}
然而,不会发生这种情况。类型 B 的实体已成功删除,但 A 实体上的 BId 仍然是非空的,任何其他对 .SaveChanges() 的调用都会抛出异常,因为这些 BId 引用的行不再存在。
如何删除 B 实体,从而使 BId 属性无效,而无需在删除操作期间手动遍历集合?
如果当前关联的实体已经加载到上下文中,外键只会自动设置为空。换句话说,当删除 b
时,关联的 A
类型的集合只会将它们的 BId
属性 设置为空,如果 A
类型的那些实体已经加载到上下文中。否则,EF 不会知道它们的存在(除非 EF 提供程序自动生成 SQL 将这些外键设置为空...在 SQL 服务器情况下它不会)。
一个选择是执行此操作(如果您不介意加载所有这些实体):
public void DeleteB(int bId)
{
var entity = _context.Bs.Single(b => b.Id == bId);
_context.Entry(entity).Collection(b => b.As).Load();
_context.Bs.Remove(entity);
_context.SaveChanges();
}
另一种选择是编写您自己的 SQL 声明并 运行 声明。