如果我有以下类:
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
状态——它只能处于Unchanged
、Added
或Deleted
。这意味着,如果您将Bar的关系从一个Foo
更改为另一个,则必须首先找到旧关系并将其设置为已删除,然后才能将新关系设置为已添加。如果你有多对多的关系,并且你还想添加、删除和更新相关对象(不仅仅是关系),这可能真的很"有趣"——尤其是你必须在某个地方保存更改的信息,才能正确设置所有状态。
关于这个问题(EF中的全局)的更多讨论在这里-它与DbContext API无关,但因为新的API只是旧的ObjectContext API的包装,所以仍然存在相同的问题。
你认为这可行吗?我不这么认为。正因为如此,你应该尽量避免这种情况。有一些方法可以避免它:
- 对附加的对象图进行更改-这意味着您将首先将实体图的原始状态附加到上下文,然后再进行所有更改
- 加载原始对象图形,然后手动将新图形中的所有更改合并到已加载(和附加)的图形中
- 在ObjectContext API的情况下,您可以使用Self-tracking实体,这些实体能够跟踪状态并自动设置应用于上下文的所有内容。它们还有一些其他的缺点和限制(例如,它们不支持延迟加载),并且它们不适用于DbContext API