C# 调用DetectChanges()时不会自动更新外键属性
我有一个非常基本的示例C#程序(简化为更复杂的程序),它使用EF6和DbContext,包含两个类:C# 调用DetectChanges()时不会自动更新外键属性,c#,entity-framework-6,dbcontext,C#,Entity Framework 6,Dbcontext,我有一个非常基本的示例C#程序(简化为更复杂的程序),它使用EF6和DbContext,包含两个类: Teacher 1...n Lesson 有一个FK约束,当删除教师实例时,该约束会将课程中的FK列设置为null 示例程序: using (var context = new EFTestEntities()) { // An instance of Teacher (named teacher) and Lesson (named lesson) are created,
Teacher 1...n Lesson
有一个FK约束,当删除教师实例时,该约束会将课程中的FK列设置为null
示例程序:
using (var context = new EFTestEntities()) {
// An instance of Teacher (named teacher) and Lesson (named lesson) are created,
// both are added to the context and context.SaveChanges() is called.
// teacher is assigned to lesson and DetectChanges() is called.
using (var context2 = new EFTestEntities()) {
// Get teacher from the DB, delete it and save the changes.
}
// Because here I know that teacher could have been changed or deleted,
// I refresh it from the database using ObjectContext.Refresh(RefreshMode.StoreWins).
// But when SaveChanges() is called,
// an SqlException concerning FK constraint violation is thrown.
}
调试时,我看到:
lesson --> teacher (Navigation Property): null (correct)
lesson --> teacher (Foreign Key Property): ID of deleted teacher (incorrect, should be null)
因为课程中的外键属性仍然指向已删除的教师,所以SqlException是有意义的
但是为什么外键属性仍然指向已删除的教师?调用DetectChanges()
时,应将其设置为null
意见:
- 不调用
并手动将导航属性设置为null:外键按预期更新。因此,Refresh()
调用一定与此问题有关Refresh()
- 调用
DbEntityEntry的
,而不是Reload()
ObjectContext的
,会导致相同的问题Refresh()
- 不仅刷新教师,还刷新课程:使
按预期更新外键。但这样一来,已经对课程进行的所有更改都将丢失DetectChanges()
DetectChanges()
再次按预期更新外键。但每次使用Refresh()
方法时,我都需要这样做。如果教师被删除,并且仍然有一节课分配给它…,当您尝试保存更改时,我甚至不确定它会是什么,它说教师实体在Refresh()后处于什么“状态”以及它有什么值。另一方面,以这种方式与事物互动似乎很奇怪。您不能使用相同的数据库上下文吗?听起来你有脱节的代码,这是一个消费的问题,应该改变,而不是试图做刷新更新陈旧的上下文意识问题。谢谢你的回答。删除教师后,课程中的FK列将设置为null。我在我的问题中加了这个。在Refresh()之后,状态保持不变。然后,除了外键属性之外,它还有来自数据库的值。但是,当调用DetectChanges()时,应该会对其进行更新。但事实并非如此。不,我不能使用相同的上下文。真正的程序要复杂得多,这是不可能的。我的猜测是,您需要再次添加它…,但这听起来像是您在以后的过程中会遇到其他问题。分离课程实例,重新附加它并将其状态设置为“修改”:确实会使DetectChanges()
再次按预期更新外键。但是每次使用Refresh()
方法时,我都需要这样做。