【发布时间】:2017-10-18 07:03:00
【问题描述】:
短版: 在执行“myDbContext.Add(Entity)”时,我添加了 2 个实体,一个是我刚刚创建的,一个是我之前查询的,但还向 dbContext 添加了一个子实体(与我查询的第一个实体相关),似乎是 EF没有将它们跟踪为存在,因为正在尝试插入父实体和子实体。
由于政策原因,我无法添加特定代码,但基本上我正在做类似的事情:
using (var db = new MyEntitiesContext())
{
/*don't know why, but code was already like this,
has some method which returns list of
SomeEntity type even knowing will have only 1 object*/
List<SomeEntity> entities = new List<SomeEntity>
entities = SomeMethod.SearchEntities(id);
SomeEntity current = entities.FirstOrDefault();
SomeEntity newOne = new SomeEntity();
//Then notice I use some of the values (all of them are int/string/date)
//from the "current" object to populate the "newOne"
newOne.Id = (from p in db.SomeEntities select p.Id).Max() + 1;
newOne.SomeDateValue = current.SomeDateValue;
newOne.someStringValue = current.someStringValue;
.
. //add some other values which doesnt' seem relevant to the issue
.
db.SomeEntity(newOne);
db.SaveChanges();
}
由于某种原因,SaveChanges 方法会导致与违反 PK 约束的子实体相关的异常。
在调试并做了一些“观察”之后,我注意到我的 dbContext 对象“db”实际上包含 SomeEntity 的 2 个实体,即“newOne”和“current”,因为db.SomeEntity.Local 属性。
出于某种原因(糟糕的设计/理解),这样做时:
db.SomeEntity.Add(newOne)
“当前”实例与子实体“状态”一起添加,因此 SaveChanges() 尝试重新插入现有的“状态”实体(除了现有的“当前”实体),这是抛出SaveChanges() 方法中的异常。
似乎我可以通过分离导致冲突的对象来解决这个问题,这些对象是“当前”实体,它是 dbContext 对象的子实体“状态”,但是
为什么会这样?或者我该如何避免?
我唯一的假设是,将值从“current”分配给“newOne”时的某些引用可能会导致该行为,请注意“status”子实体没有从“current”分配给“newOne”,我我尝试使用“状态”实体的新实例进行分配并将其保留为空,但这些都不能解决问题。
注意:我尝试在不同的“使用”块中查询“当前”对象,但问题仍然存在。
注意 2:在 SaveChanges 方法之前,代码编译和执行良好,上面的示例不是实际代码,而是一个缩短/虚构版本,试图代表存在问题的实际代码的同一部分,所以可以在上面的代码中找到一些语法/其他错误,这个问题更多地与我对实体框架如何工作和/或在添加/保存更改时跟踪实体缺乏了解
上次更新 SearchEntities 方法使用不同的上下文,通过在不同的上下文中“缓存”实体,我导致 EF 将它们标记为 new-for insert,我只是将该方法的代码取出以在同一个 dbContext 中使用它正在插入一个新实体并解决了这个问题,这似乎是一个非常常见的问题,但由于它的性质,每个开发人员都觉得自己陷入了陷阱。
【问题讨论】:
-
您是否确保您的“类似”代码也可以编译并产生相同的问题?
-
@Damien_The_Unbeliever 不,遗憾的是我刚刚创建的示例确实按预期工作,实际上我在 db 对象中看到了 2 个“SomeEntity”,但子实体没有被添加到 db 对象并且 SaveChanges 方法执行时没有错误,因此问题不存在,但即使在分离子实体时的“真实”问题中,“当前”也会导致其表上的 PK 冲突
-
我认为上下文将包含 2 个值,因为被跟踪的实体..
-
@RJ- 嗨,是的,这似乎是意料之中的,我刚刚创建了一个只有 2 个表的快速示例,我看到这种行为和插入效果很好,但似乎有问题的实际代码正在做出了点问题或者模型搞砸了(很多人都接触过那个应用程序),在代码有问题的情况下,我还看到了 2 个实体,buuuuut 我还添加了一个子“状态”实体并导致主键约束错误,即使我分离子实体,父“当前”也会导致另一个错误,因为 EF 试图插入它(并且已经存在于表中)
标签: c# asp.net-mvc entity-framework