【问题标题】:Saving a single entity instead of the entire context保存单个实体而不是整个上下文
【发布时间】:2009-08-19 17:31:43
【问题描述】:

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

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

【问题讨论】:

  • 到目前为止我还没有看到这样做的方法......它可能是正确的。您要查找的内容可能会导致数据不一致。

标签: c# entity-framework


【解决方案1】:

最佳实践?此外,您的意思是“不要这样做!”?

我认为没有最佳实践可以使 ObjectContext 与数据库的状态不同。

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

【讨论】:

  • 使用单独的上下文是一个很好的方法。过程基本上是:1)创建另一个 ObjectContext 并附加附加子对象 2)设置父导航属性的 EntityKey 3)保存新上下文,然后分离子项 4)将子项附加到“主”上下文跨度>
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    这可以通过使用 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();
    }
    

    【讨论】:

    • 有道理 - 但是如果我仍然需要跟踪然后将更改提交到父对象,我将在执行 AcceptAllChanges() 后失去执行此操作的能力(正确吗?)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 1970-01-01
    • 2019-08-09
    相关资源
    最近更新 更多