我正在使用EF 4,POCO。任务如下:拥有一组DomainObject类型的数据,需要从数据库中获取并在断开连接模式下更新(添加,更新,删除操作)。如何将更新的集合稍后推送回数据库?假设我们加载数据后没有对表进行并行更改。我知道context.SaveChanges()做了更新,但问题是如何将所有更改从有点列表中放回到DbSet,或者可能有一种方法可以在断开模式下直接使用DbSet?谢谢!
答案 0 :(得分:7)
自跟踪实体是EDMX + ObjectContext API的特性,因此如果您的映射/代码依赖于DbContext API(您提到DbSet
),则无法使用它们。自跟踪实体是变更集模式的实现(与旧数据集一样)。关于SO的一些参考:
如果您不使用自我跟踪实体,答案非常简单 - 您必须说EF您做了哪些更改。使用分离的实体后,您必须将实体附加回新的上下文并手动说出您的确切操作=插入,更新,删除的内容以及您如何更改关系。此过程中的关键组件是ObjectContext API中的ObjectStateManager
(context.ObjectStateManager
)或DbContext API中的DbChangeTracker
(context.ChangeTracker
)。在处理关系时,这是非常困难的,因此我们很多人通常使用另一个进程:我们再次加载实体图并将更改从分离的实体图合并到附加的实体图。一些参考文献:
请注意,根据您要执行的更新次数,整个过程可能会非常慢。原因是EF doesn't support command batching所以每次插入,更新,删除都是在单独的数据库往返中执行的。如果更新100.000复杂对象,则可能需要执行SaveChanges
几分钟。
编辑:
在一些非常特殊的情况下,您只使用没有关系的实体,您可以使用技巧来传输有关“更改”的信息:
public void ProcessChanges(IEnumerable<DomainObject> entities)
{
foreach(var entity in entities)
{
if (entity.Id == 0)
{
// New entity
}
else if (entity.Id > 0)
{
// Modified entity (you cannot say if entity war really modified,
// you must update it always).
}
else
{
// Use negative Id (origId * -1) to mark entity as deleted
// reverse Id and delete entity
}
}
}
这仅适用于带有简单键的扁平物体。
答案 1 :(得分:-1)