这个问题已经以 50 种不同的方式被问了 500 次...但又来了,因为我似乎找不到我正在寻找的答案:
我将 EF4 与 POCO 代理一起使用。
一个。 我有一张从 ObjectContext 的一个实例中获取的对象图。该 ObjectContext 已处理。
B. 我有一个从 ObjectContext 的另一个实例中获取的对象。该 ObjectContext 也已被释放。
我想使用 B 中的实体为 A 中的一堆事物设置相关属性......类似
foreach(var itemFromA in collectionFromA)
{
itemFromA.RelatedProperty = itemFromB;
}
当我这样做时,我得到了异常:
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
我想我需要在处理这些实体时将它们从 ObjectContext 中分离出来,以便上面的工作......问题是,在处理时从我的 ObjectContext 中分离所有实体似乎会破坏图形。如果我做类似的事情:
objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged)
.Select(i => i.Entity).OfType<IEntityWithChangeTracker>().ToList()
.ForEach(i => objectContext.Detach(i));
图中的所有关系似乎都未设置。
我该如何着手解决这个问题?
最佳答案
@Danny Varod 是对的。您应该为整个工作流使用一个 ObjectContext
。此外,因为您的工作流程似乎是一个包含多个窗口的逻辑功能,所以它可能也应该使用单个演示者。然后您将遵循推荐的方法:每个演示者一个上下文。您可以多次调用 SaveChanges
,这样它就不会破坏您的逻辑。
此问题的根源是众所周知的问题,即在 POCO 实体之上生成的动态代理不足以及 POCO T4 模板生成的 Fixup 方法。当您处置它时,这些代理仍然持有对上下文的引用。正因为如此,他们认为他们仍然依附于上下文,他们不能依附于另一个上下文。如何强制他们释放对上下文的引用的唯一方法是手动分离。同时,一旦您将一个实体从上下文中分离出来,它就会从相关的附加实体中移除,因为您不能在同一个图中混合使用附加和分离的实体。
您调用的代码实际上没有出现问题:
itemFromA.RelatedProperty = itemFromB;
但是在Fixup方法触发的反向操作中:
itemFromB.RelatedAs.Add(itemFromA);
我认为解决这个问题的方法是:
- 不要这样做并为整个工作单元使用单一上下文 - 这是假定的用法。
- 删除反向导航属性,以便 Fixup 方法不会触发该代码。
- 不要将 POCO T4 模板与 Fixup 方法一起使用或修改 T4 模板以不生成它们。
- 关闭这些操作的延迟加载和代理创建。这将从您的 POCO 中删除动态代理,因此它们将独立于上下文。
要关闭代理创建和延迟加载使用:
var context = new MyContext();
context.ContextOptions.ProxyCreationEnabled = false;
您实际上可以尝试编写自定义方法来分离整个对象图,但正如您所说,它被问了 500 次而且我还没有看到可行的解决方案 - 除了对新对象图的序列化和反序列化。
关于c# - Entity Framework 多对象上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5693843/