c# - 在断开连接的环境 (EF) 中使用 Db 生成的 ID 更新实体图 ID

标签 c# entity-framework ef-code-first repository graphdiff

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

  1. 使用 Linq to entities 读取实体图(阅读DbContext后处理)
  2. 显示已读Entity给最终用户的图表。
  3. 最终用户可以将此更改应用于 Entity图形:
    • 更新根实体
    • 添加一些子实体
    • 编辑一些子实体
    • 删除一些子实体
  4. 用户调用一个方法来保存他对 Db 的更改
  5. 创建一个新的 DbContext实例。
  6. 重新加载相同的 Entity图表来自 Db
  7. 使用 AutoMapper 将所有属性的值从用户实体映射到重新加载的实体
  8. 将6步的结果实体附加到我的DbContext使用 GraphDiff
  9. 调用 DbContext.SaveChanges();保留对 Db 的更改 enter image description here

    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.IdChild22.Identity对象是 0然而,我可以手动更新 Id s 但我正在寻找通用 方式来更新这些 Id Db 的值生成 Id

最佳答案

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

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

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

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 到数据库。至少您可以通过一种相当一致的方式来识别要同步的对象。

关于c# - 在断开连接的环境 (EF) 中使用 Db 生成的 ID 更新实体图 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25154882/

相关文章:

c# - 修改edmx模板文件

c# - EF 4.1 双向一对一问题

c# - 如何让随机数/字母生成器生成 3 个字母然后生成 6 个数字?在 WPF 中

c# - dbcontext 上的 Entity Framework 选择子句

c# - EF 核心 - 为没有连接字符串和另一个类库中的数据库创建迁移

mysql - 使用 code first 和 mysql 插入中文数据时出现问题

windows-services - TopShelf、Ninject 和 EF 代码优先的 Ninject 范围问题

c# - 我的 Windows 服务实例需要一个贡献函数

c# - 如何升级 Entity Framework 5 Code First 的 DataAnnotations

c# - 如何从 HBITMAP 转换为 .NET 的 Bitmap 类?