新子项在Entity Framework 4中插入现有父项

时间:2013-04-09 15:34:21

标签: c# entity-framework entity-framework-4 silverlight-5.0

当我尝试向现有父对象添加新的子关系时,实体尝试将父对象插入 new ,而不是将其更新为已修改 。我收到错误消息称其尝试 插入重复的密钥

这真的让我感到困惑,直到我用新关系更新模型(通过数据库更新,而不是代码优先),它才表现得像这样。在相同上下文中具有相同多对多模式的其他表不会导致此错误!

我发现如果我将我的子对象添加到上下文中,仔细设置ID值,而不是导航属性,它将保存正常。 但修复过程不会将子对象添加到导航集合,这会导致其他地方出现逻辑问题。

我的模型有很多这样的关系:

选项 - < optionUnit> - 单位

Option和Unit对象都现有已加载进入上下文。

通常我会制作桥牌表并设置如下的导航属性:

bridge = new OptionUnit()
{
    OptionUnitId = Guid.NewGuid(),
    Unit = SelectedUnit,
    Option = SelectedOption,
};
//Context.OptionUnits.Add(bridge); //added to context via the navigation properties

但是当我这样做的时候,实体试图将SelectedOption插入为新的(即使它的实体状态在保存时被修改,而不是新的或分离的。)

为了解决这个问题,我不得不建立桥梁并设置id。我在保存时没有收到任何错误,但它不会像我期望的那样通过修复自动添加到SelectedOption.OptionUnits。如果我手动将它添加到集合中,我会再次收到保存错误。

bridge = new OptionUnit()
{
    OptionUnitId = Guid.NewGuid(),
    //Unit = SelectedUnit,
    UnitId = SelectedUnit.UnitId,
    //Option = SelectedOption,
    OptionId = SelectedOption.OptionId,
};
Context.OptionUnits.Add(bridge);

这似乎只发生在选项实体的关系上。另外一个关系,在optionUnit> - Unit之间没有任何问题,并按预期工作。

关系似乎有点不对,但我不确定在哪里看。 我需要知道导致这种行为的原因,如何修复它,以及如何防止它在将来发生....

2 个答案:

答案 0 :(得分:3)

令人难以置信的是,Julie Lerman刚刚收到了一篇关于这个确切问题及其发生原因的MSDN文章。您可以找到文章right here

以朱莉自己的话说:

  

它发生的原因是当你使用DbSet.Add方法时,不仅将根实体的状态标记为“已添加”,而且图中上下文之前未知的所有内容都标记为已添加。 。即使开发人员可能知道该对象具有现有Id值,Entity Framework也会尊重其EntityState(已添加)并为该对象创建Insert数据库命令,而不管现有Id。

所以这里简单地说,当你说Context.OptionUnits.Add(bridge);时,它也认为你也试图将Option和Unit对象添加到它。相反,你需要使用FK(如她提到的那样),然后添加它。

我认为那是你在那里第二次尝试时所做的,但我想知道你是如何检查它是否在SelectedOption.OptionUnits中。保存后是否正在尝试检查?在这种情况下,它不会显示,因为当Entity Framework提取该值时,该值会缓存在内存中。之后你需要尝试再次提出该对象。

答案 1 :(得分:0)

我发现了这个问题。添加子项后,我会运行一些逻辑来更新一些总计。问题是我使用了RaiseDataMemberChanged(“sum”)而不是RaisePropertyChanged(“sum”)。 RaiseDataMemberChanged()必须将实体中的某些内容标记为已修改,并且正在解决此问题。 感谢IronMan84的所有帮助。