我正在使用 EF6 code first
在WinForm
项目。
我使用以下方法从 Db
中读取实体,更新它们,然后将它们保存回 Db
:
- 使用
Linq to entities
读取实体图(阅读DbContext
后处理) - 显示已读
Entity
给最终用户的图表。 - 最终用户可以将此更改应用于
Entity
图形:- 更新根实体
- 添加一些子实体
- 编辑一些子实体
- 删除一些子实体
- 用户调用一个方法来保存他对
Db
的更改 - 创建一个新的
DbContext
实例。 - 重新加载相同的
Entity
图表来自Db
- 使用
AutoMapper
将所有属性的值从用户实体映射到重新加载的实体 - 将6步的结果实体附加到我的
DbContext
使用GraphDiff
调用
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
和 Child22.Id
在 entity
对象是 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/