3

我正在EF6 code first一个WinForm项目中工作。我使用以下方法从中读取实体Db,更新它们,然后将它们保存回Db

  1. Linq to entities使用(阅读DbContext处置后)阅读实体图
  2. 向最终用户显示读取Entity的图表。
  3. 最终用户可以将此更改应用于Entity图形:
    • 更新根实体
    • 添加一些子实体
    • 编辑一些子实体
    • 删除一些子实体
  4. 用户调用一个方法来将他的更改持久化到Db
  5. 创建一个新DbContext实例。
  6. 重新加载相同Entity的图表Db
  7. 使用将所有属性的值从用户实体映射到重新加载的实体AutoMapper
  8. 将 6 步的结果实体附加到我的DbContextusingGraphDiff
  9. 调用DbContext.SaveChanges();以保持更改Db 在此处输入图像描述

    var root = new MyDbcontext()
                               .Roots
                               .LoadAggregation()
                               .ToList();
                               //    LoadAggregation in this case, means following codes:   
                               //    .Include("Child1")   
                               //    .Include("Child2")
    
    root.Child1s.Remove(child11);
    root.Child1.Add(Child13); // 
    root.Child2.Add(Child22);
    using(var uow = new UnitOfWork())   
    {
        uow.Repository<Root>().Update(root);
        uow.Repository<AnotherRoot>().Update(anotherRoot); //user may want to update multiple Roots
        uow.SaveChanges();   <---- at this point Child13.Id and  Child22.Id generated by Db
    }
    

    public void Update(Root entity) //Update method in my Repository class
    { 
       var context = new MyDbcontext();
       var savedEntity = context.Roots //reload entity graph from db
                                .LoadAggregation()
                                .ToList();
       Mapper.Map(entity,savedEntity); // map user changes to original graph
       context.UpdateGraph(savedEntity, savedEntity.MappingConfiguration); // attach updated entity to dbcontext using graphdiff
    } 

    public void SaveChanges() // SaveChanges() in UnitofWork class
    {  
      context.SaveChanges();
    }

它工作正常,

在第二张图中,用户添加了 Child13 和 Child22,当我调用uow.SaveChanges()它们时,它们将保存到Db并且它们Id的 s 将被分配。但是在对象中Child13.Id,我可以手动更新s 但我正在寻找通用方法来使用生成的 s更新这些值。Child22.Identity0IdIdDbId

4

1 回答 1

3

就个人而言,我会采取稍微不同的方法。

像这样的事务不应该跨越多个上下文。即使您可以手动更新这些 ID,您也需要某种替代方法来识别这些子对象,以确保您将对象实例与数据库分配的 ID 正确同步。或者这些对象的其他方面可能在瞬态时被更新,并且也需要应用于数据库。一般来说,从不同 DBContext 加载的对象是不同的对象,即使它们具有相同的数据库标识,除非您在 EF 之上实现了某种缓存。

我会做这样的事情。使用一个上下文,并让 EF 通过在您需要执行持久性操作的地方注入上下文来为您管理所有标识:

var context = new MyDbcontext();
var root = context
                           .Roots
                           .LoadAggregation()
                           .ToList();
                           //    LoadAggregation in this case, means following codes:   
                           //    .Include("Child1")   
                           //    .Include("Child2")

root.Child1.Remove(child11);
root.Child1.Add(Child13); // 
root.Child2.Add(Child22);
using(var uow = new UnitOfWork())   
{
    uow.Repository<Root>().Update(root, context);
    uow.Repository<AnotherRoot>().Update(anotherRoot, context); //user may want to update multiple Roots
    uow.SaveChanges(context);   <---- at this point Child13.Id and  Child22.Id generated by Db
}

public void Update(Root entity, MyDbcontext context) //Update method in my Repository class
{ 
   var savedEntity = context.Roots //reload entity graph from db
                            .LoadAggregation()
                            .ToList();
   Mapper.Map(entity,savedEntity); // map user changes to original graph
   context.UpdateGraph(savedEntity, savedEntity.MappingConfiguration); // attach updated entity to dbcontext using graphdiff
} 

public void SaveChanges(context) // SaveChanges() in UnitofWork class
{  
  context.SaveChanges();
}

如果由于某种原因您无法使用相同的上下文,您可能需要考虑向子对象添加某种额外的标识字段,例如 Guid,并在持久化回数据库之前将其写入子对象通过 SaveChanges。至少您有一种相当一致的方法来识别要同步的对象。

于 2014-08-13T22:54:34.303 回答