实体框架多对象上下文

Jef*_*eff 5 .net c# architecture entity-framework entity-framework-4

这个问题已经以50种不同的方式被问到了500个不同的时间......但是这里又一次,因为我似乎无法找到我正在寻找的答案:

我正在使用EF4和POCO代理.

答:我有一个从ObjectContext的一个实例中获取的对象图.该ObjectContext被释放.

B.我有一个从ObjectContext的另一个实例获取的对象.ObjectContext也被处理掉了.

我想在A中使用B中的实体设置一堆相关的属性....类似于

foreach(var itemFromA in collectionFromA)
{
   itemFromA.RelatedProperty = itemFromB;
}
Run Code Online (Sandbox Code Playgroud)

当我这样做时,我得到了例外:

System.InvalidOperationException occurred
  Message=The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
  Source=System.Data.Entity
  StackTrace:
       at System.Data.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)
       at System.Data.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedEntity, Boolean applyConstraints)
       at System.Data.Objects.DataClasses.EntityReference`1.set_ReferenceValue(IEntityWrapper value)
       at System.Data.Objects.DataClasses.EntityReference`1.set_Value(TEntity value)
       at 
Run Code Online (Sandbox Code Playgroud)

我想我需要将这些实体从ObjectContexts中分离出来,以便上面的代码可以工作......问题是,当它处理时从我的ObjectContext中分离所有实体似乎会破坏图形.如果我这样做:

objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged)  
.Select(i => i.Entity).OfType<IEntityWithChangeTracker>().ToList()  
.ForEach(i => objectContext.Detach(i));
Run Code Online (Sandbox Code Playgroud)

图中的所有关系似乎都未被设置.

我怎样才能解决这个问题?

Lad*_*nka 11

@Danny Varod是对的.您应该使用一个ObjectContext用于整个工作流程.此外,因为您的工作流程似乎是包含多个窗口的一个逻辑功能,所以它应该也可以使用单个演示者.然后,您将遵循建议的方法:每个演示者的单个上下文.你可以SaveChanges多次调用,这样就不会破坏你的逻辑.

该问题的根源是众所周知的问题,即在POCO实体之上生成的动态代理的缺陷与POCO T4模板生成的Fixup方法相结合.当您处置它时,这些代理仍然引用上下文.因此,他们认为他们仍然依附于上下文,他们不能被附加到另一个上下文.强制它们释放对上下文的引用的唯一方法是手动分离.同时,一旦从上下文中分离实体,它就会从相关的附加实体中删除,因为您不能在同一个图中混合使用附加实体和分离实体.

您调用的代码中实际上没有出现此问题:

itemFromA.RelatedProperty = itemFromB;
Run Code Online (Sandbox Code Playgroud)

但是在Fixup方法触发的反向操作中:

itemFromB.RelatedAs.Add(itemFromA);
Run Code Online (Sandbox Code Playgroud)

我认为解决这个问题的方法是:

  • 不要这样做,并为整个工作单元使用单个上下文 - 这是所谓的用法.
  • 删除反向导航属性,以便Fixup方法不会触发该代码.
  • 不要将POCO T4模板与Fixup方法一起使用或修改T4模板以不生成它们.
  • 关闭这些操作的延迟加载和代理创建.这将从您的POCO中删除动态代理,因此它们将独立于上下文.

要关闭代理创建和延迟加载,请使用:

var context = new MyContext();
context.ContextOptions.ProxyCreationEnabled = false;
Run Code Online (Sandbox Code Playgroud)

您实际上可以尝试编写自定义方法来分离整个对象图,但正如您所说的那样,它被要求500次并且我还没有看到工作解决方案 - 除了对新对象图的序列化和反序列化.


Dan*_*rod 5

我想你在这里有几个不同的选择,其中2个是:

  1. 在完成该过程之前保持上下文有效,仅使用1个上下文,而不是2.

  2. 一个.在处理上下文#1之前,使用BinaryStreamer或ValueInjecter或AutoMapper 等工具创建图的深层克隆.

    湾 合并从上下文#2到克隆图的更改.

    C.保存后,将克隆图形中的更改合并到由新ObjectContext创建的图形中.


为了将来参考,这个MSDN博客链接可以帮助您决定在以下时间做什么:http: //blogs.msdn.com/b/dsimmons/archive/2008/02/17/context-lifetimes-dispose-or-reuse. ASPX