我有两个实体,它们定义并配置了可选的1对多关系:
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仍为非null,而对.SaveChanges()的任何其他调用都会抛出异常,因为这些BId引用的行不再存在。
如何以一种使BId属性无效的方式删除B实体,而不必在删除操作期间手动迭代该集合?
答案 0 :(得分:1)
如果当前关联的实体已加载到上下文中,则外键仅会自动设置为null。换句话说,当删除b
时,如果类型为A
的实体已加载,则BId
类型的关联集合只会将其A
属性设置为null进入上下文。否则,EF将不知道它们的存在(除非EF提供程序自动生成SQL,将这些外键设置为null ...在SQL Server的情况下不会这样做。)
一种选择是这样做(如果你不介意加载所有这些实体):
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语句并运行它。