2015-07-20 76 views
0

我有一个具有可选1对多的关系,定义和配置这样两个实体:删除可选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); 
    } 
} 

当的实体删除类型BI期望所有具有到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()的调用都会引发异常,因为这些BIds正在引用不再存在的行。

如何以删除BId属性的方式删除B实体,而无需在删除操作期间手动迭代集合?

回答

1

如果当前关联的实体已经加载到上下文中,外键只会自动设置为空。换句话说,当b被删除时,如果A类型的实体已被加载到上下文中,那么A类型的关联集合只会将其BId属性设置为空。否则,EF不会知道它们的存在(除非EF提供程序自动生成SQL,将这些外键设置为空......它不在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语句,并运行。

+0

我可以在A表上运行一个'update A a set a.BId = NULL,其中a.BId = @ bId'作为''before delete''触发器。 – user1569339