1

当我尝试将新的子关系添加到现有父对象时,实体会尝试将父对象插入为new,而不是将其更新为modified。我收到一条错误消息,说它试图插入重复的密钥

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

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

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

option -< 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 之间的其他关系没有问题并且按预期工作。

似乎关系有问题,但我不确定在哪里看。我需要知道是什么导致了这种行为,如何解决它,以及如何防止它在未来发生......

4

2 回答 2

3

令人难以置信的是,Julie Lerman 刚刚发表了一篇关于这个确切问题及其发生原因的令人惊叹的 MSDN 文章。你可以在这里找到这篇文章。

用朱莉自己的话来说:

发生这种情况的原因是,当您使用 DbSet.Add 方法时,不仅根实体的状态被标记为“已添加”,而且图中上下文之前不知道的所有内容也被标记为已添加。即使开发人员可能知道该对象有一个现有的 Id 值,Entity Framework 还是尊重其 EntityState (Added) 并为该对象创建一个插入数据库命令,而不考虑现有的 Id。

因此,简而言之,当您说 时Context.OptionUnits.Add(bridge);,它还认为您也在尝试向其添加 Option 和 Unit 对象。相反,您需要使用 FK(正如她所提到的)然后添加它。

我认为这就是您在第二次尝试中尝试做的事情,但我想知道您如何检查它是否在SelectedOption.OptionUnits. 保存后是否要立即检查?在这种情况下,它不会显示,因为当它被实体框架拉取时,该值被缓存在内存中。之后您需要再次尝试调出该对象。

于 2013-04-10T15:16:40.883 回答
0

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

于 2013-04-11T14:18:42.773 回答