删除可选的一对多不会将外键设置为空

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 声明并 运行 声明。