2011-07-14 98 views
5

在ASP.NET MVC 2中,使用实体框架4时,出现“IEntityChangeTracker的多个实例无法引用实体对象”的错误。每个HttpContext只使用一个ObjectContext的C#实体框架

SO的搜索表明它可能是因为我有不同的实体框架ObjectContext的实例,它应该只是每个HttpContext的一个ObjectContext实例。

我有这样的代码(写入很久之前我加入),似乎做到这一点 - 每个HttpContext有一个ObjectContext。但我经常收到“IEntityChangeTracker”异常所以它可能不会如预期运行:

// in ObjectContextManager.cs 
public const string ConnectionString = "name=MyAppEntities"; 
public const string ContainerName = "MyAppEntities"; 

public static ObjectContext GetObjectContext() 
{ 
    ObjectContext objectContext = GetCurrentObjectContext(); 
    if (objectContext == null) // create and store the object context 
    { 
     objectContext = new ObjectContext(ConnectionString, ContainerName);  
     objectContext.ContextOptions.LazyLoadingEnabled = true;  
     StoreCurrentObjectContext(objectContext); 
    } 
    return objectContext; 
} 

private static void StoreCurrentObjectContext(ObjectContext objectContext) 
{ 
    if (HttpContext.Current.Items.Contains("EF.ObjectContext")) 
     HttpContext.Current.Items["EF.ObjectContext"] = objectContext; 
    else 
     HttpContext.Current.Items.Add("EF.ObjectContext", objectContext); 
} 

private static ObjectContext GetCurrentObjectContext() 
{ 
    ObjectContext objectContext = null; 
    if (HttpContext.Current.Items.Contains("EF.ObjectContext") 
     objectContext = (ObjectContext)HttpContext.Current.Items["EF.ObjectContext"]; 
    return objectContext; 
} 

我已经研究这个代码,它看起来是正确的。它尽我所能地告诉为每个HttpContext返回一个ObjectContext实例。代码是否错误?

如果代码没有错,为什么我会得到“一个实体对象不能被多个IEntityChangeTracker实例引用”异常?

编辑:要显示的ObjectContext是如何布置:

// in HttpRequestModule.cs 
private void Application_EndRequest(object source, EventArgs e) 
{ 
    ServiceLocator.Current.GetInstance<IRepositoryContext>().Terminate(); 
} 

// in RepositoryContext.cs 
public void Terminate() 
{ 
    ObjectContextManager.RemoveCurrentObjectContext(); 
} 

// in ObjectContextManager.cs 
public static void RemoveCurrentObjectContext() 
{ 
    ObjectContext objectContext = GetCurrentObjectContext(); 
    if (objectContext != null) 
    { 
     HttpContext.Current.Items.Remove("EF.ObjectContext"); 
     objectContext.Dispose(); 
    } 
} 
+0

你在EndRequest方法中处理上下文吗? – Akhil

+0

已更新为显示处置方法 –

回答

5

我的猜测是,你在什么地方存储对象在内存中(最有可能使用过程中的模式HTTP缓存,但也可能是任何手动缓存,例如共享字典),现在你已经有了某种联系别的东西该对象,例如:

newOrder.OwnerUser = currentUser; // <== let's say currentUser came from cache 
            // and newOrder was on your new entity context 

因此,如果缓存的对象仍然认为它是连接到一个上下文中的问题;尤其是,您可能会意外地保持整个图形。


代码看起来OK(只要你是在请求结束处置它),但是这将是一个很好的时间来补充:

private const string EFContextKey = "EF.ObjectContext"; 

和使用,在地方5个文字。避免一些风险; p

+0

其实我已经将一个对象存储在缓存(货币DefaultCurrency)中,然后将其附加到订单对象(order.Currency = DefaultCurrency) - 这正是抛出异常的地方..这是一个非常很有前途。当我保存DefaultCurrency缓存时,它的类型是'System.Data.Entity.DynamicProxies.Currency_F4008E27DE_etc',而不是POCO类'Entities.Currency'。我需要如何处理这个对象,才能够安全地将它存储在缓存中,然后再将它添加到另一个对象中,然后将它分离出来? –

+1

@JK - 棘手;因为可能有多个线程一次尝试使用它,所以我可以建议的最好的方法是编写一些克隆它的代码(创建一个未附加到上下文的vanilla POCO),并存储一个克隆(避免保持图形存活的风险),并且每次将它取出时再次克隆*。我不知道在EF中是否可能,但如果这是L2S,我会设置DefaultCurrencyId而不是DefaultCurrency,这样可以避免一些问题。 –

+0

谢谢,我会看看我能在那里做些什么 –

相关问题