保存单个实体而不是整个上下文

时间:2009-08-19 17:31:43

标签: c# entity-framework

我遇到的情况是,我基本上需要将一对多关联的子实体的更改写入数据库,但不保存对父实体所做的任何更改。

实体框架目前处理上下文范围(EntityContext.SaveChanges())中的数据库提交,这对于强制执行关系等是有意义的。但我想知道是否有一些最佳实践或者可能是推荐的方法关于对个人entite而不是整个上下文进行细粒度数据库提交。

3 个答案:

答案 0 :(得分:8)

最佳做法?除此之外,你的意思是“不要这样做!”?

我认为没有一种最佳做法可以使ObjectContext与数据库的状态不同。

如果你必须这样做,我会新建一个新的ObjectContext并在那里对子实体进行更改。这样,两种情境都是一致的。

答案 1 :(得分:4)

我有类似的需求。我正在考虑的解决方案是在所有实体上实现包装器属性,这些实体私下存储任何属性更改,而不会影响实际的实体属性。然后,我将向实体添加一个SaveChanges()方法,该方法将更改写入实体,然后在上下文中调用SaveChanges()。

这种方法的问题在于您需要使所有实体都符合此模式。但是,它似乎工作得很好。它确实有另一个缺点,如果你对包含大量数据的很多对象进行了很多更改,你最终会在内存中留下无关的副本。

我能想到的唯一其他解决方案是,在保存更改后,保存所有已更改/添加/删除的实体的实体状态,将它们设置为未修改,除了您要更改的实体,保存更改,然后还原其他实体的状态。但这听起来可能很慢。

答案 2 :(得分:2)

这可以通过使用AcceptAllChanges()来完成。

对父实体进行更改,调用AcceptAllChanges(),然后对相关实体进行更改并调用SaveChanges()。您对父项所做的更改将不会保存,因为它们已“提交”到实体但未保存到数据库中。

using (AdventureWorksEntities adv = new AdventureWorksEntities())
{
     var completeHeader = (from o in adv.SalesOrderHeader.Include("SalesOrderDetail")
                             where o.DueDate > System.DateTime.Now
                             select o).First();
     completeHeader.ShipDate = System.DateTime.Now;
     adv.AcceptAllChanges();
     var details = completeHeader.SalesOrderDetail.Where(x => x.UnitPrice > 10.0m);
     foreach (SalesOrderDetail d in details)
     {
          d.UnitPriceDiscount += 5.0m;     
     }
          adv.SaveChanges();
}