实体框架 - 代码优先 - 当我未将父对象设置为 EntityState 时,如何保存 ICollection。



如果我有以下类:

public class Foo()
{
public int PropertyIWantUpdated {get; set;}
public int PropertyIDontWantUpdated (get; set}
public ICollection<Bar> Bars {get; set;}
}

保存到我的数据库时,而不是

context.Entry(thisFoo).State = EntityState.Modified;

我正在使用

context.Entry(thisFood).Property(tf => tf.PropertyIWantUpdated).IsModified = true;

如何保存对条形图的更改?

这取决于您尝试更新的内容。首先,让我澄清一个重要的事实-如果你有分离的实体图(更多有关系的实体),并且你想把所有的变化都传递给EF,你有责任告诉EF每个实体和每个关系中发生了什么变化-EF不会帮你。

如果您尝试只更新Bar实例,并且没有更改关系(=没有向Foo添加新的Bar或从Foo删除Bar),则只需要迭代Bars并将其设置为Modified状态。

如果您还更改了Bars集合的内容,整个过程将变得非常复杂,方法取决于您定义实体的方式=如果您使用独立或外键关联。

在外键关联的情况下(Bar具有FK作为属性=在Bar中,您具有类似于FooId的属性),您遵循与开头类似的方法。您迭代Bars并将状态设置为:

  • 如果现有Bar被分配给Foo,则为Modified
  • 如果新的Bar被分配给Foo,则为Added

有一个大问题。如果从Bars集合中删除了一些Bar实例,则还必须将它们附加到上下文中,并相应地设置它们的状态:

  • Modified如果FK应设置为null
  • 如果Bar应删除,则为Deleted

这一切只针对一对多的关系。

如果你认为以前的方法很复杂,请准备好,在独立关联的情况下(Bar不具有FK属性——对于多对多关系来说总是如此),过程会更糟。独立关联有自己的对象跟踪状态=在Bar实体上设置状态不会持久化新关系。第一个问题是无法从DbContext API直接访问此对象-必须将DbContext转换为ObjectContext,并使用ObjectStateManager来访问表示关系的ObjectStateEntry。之后,您必须正确设置它的状态,这并不像看上去那么容易,因为关系不能处于Modified状态——它只能处于UnchangedAddedDeleted。这意味着,如果您将Bar的关系从一个Foo更改为另一个,则必须首先找到旧关系并将其设置为已删除,然后才能将新关系设置为已添加。如果你有多对多的关系,并且你还想添加、删除和更新相关对象(不仅仅是关系),这可能真的很"有趣"——尤其是你必须在某个地方保存更改的信息,才能正确设置所有状态。

关于这个问题(EF中的全局)的更多讨论在这里-它与DbContext API无关,但因为新的API只是旧的ObjectContext API的包装,所以仍然存在相同的问题。

你认为这可行吗?我不这么认为。正因为如此,你应该尽量避免这种情况。有一些方法可以避免它:

  • 对附加的对象图进行更改-这意味着您将首先将实体图的原始状态附加到上下文,然后再进行所有更改
  • 加载原始对象图形,然后手动将新图形中的所有更改合并到已加载(和附加)的图形中
  • 在ObjectContext API的情况下,您可以使用Self-tracking实体,这些实体能够跟踪状态并自动设置应用于上下文的所有内容。它们还有一些其他的缺点和限制(例如,它们不支持延迟加载),并且它们不适用于DbContext API

相关内容

  • 没有找到相关文章

最新更新