首先在我的 EF4.3 代码中(但使用明确设计的数据库,而不是由 EF 生成的数据库),我有以下问题。
我有一个实体“WorkPlan”,它可以包含一对多的“Break”实体。在模型中,工作计划有一个 ICollection,但 Break 不知道工作计划。
这是一种聚合关系。“中断”不能存在于工作计划范围之外。
我想要发生的是,当我从工作计划的休息时间集合中删除休息时间时,应该在保存更改时在数据库中删除该休息时间:
[Test]
public void ShouldRemoveBreakInDatabase()
{
// Setup
var workPlan = WorkPlanBuilder.Build(x => x.AddBreak());
Save(workPlan);
// Exercise
var exerciseContext = CreateDataContext();
workPlan = exerciseContext.WorkPlans.Single();
workPlan.RemoveBreak(workPlan.Breaks.Single());
exerciseContext.SaveChanges();
// Verify
var actual = SqlHelper.ExecuteScalar("select count(*) from Breaks");
Assert.That(actual, Is.EqualTo(0));
}
但是,SaveChanges() 调用会导致以下异常:
System.Data.Entity.Infrastructure.DbUpdateException :保存不为其关系公开外键属性的实体时发生错误。EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅 InnerException。
----> System.Data.UpdateException : 更新条目时出错。有关详细信息,请参阅内部异常。
----> System.Data.SqlClient.SqlException:无法将值 NULL 插入到列“WorkPlan_Id”、表“ActivityStore.dbo.Breaks”中;列不允许空值。更新失败。该语句已终止。
似乎很清楚,当从 WorkPlan 的集合中删除 Break 时,EF 假定它应该在数据库中将 WorkPlan_Id 字段设置为 null,但该字段不可为 null。
将以下内容添加到我的数据上下文中:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<WorkPlan>().HasMany(x => x.Breaks).WithRequired();
}
导致不同的异常:
System.Data.Entity.Infrastructure.DbUpdateException :保存不为其关系公开外键属性的实体时发生错误。EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅 InnerException。
----> System.Data.UpdateException:来自“WorkPlan_Breaks”关联集的关系处于“已删除”状态。给定多重约束,相应的“WorkPlan_Breaks_Target”也必须处于“已删除”状态。
有没有一种简单的方法可以做到这一点?