每个HttpContext只使用一个ObjectContext的C#Entity Framework

在ASP.NET MVC 2中,使用Entity Framework 4,我收到此错误“实体对象不能被IEntityChangeTracker的多个实例引用”。

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

我有这个代码(在我加入之前写的很久)似乎就是这样 – 每个HttpContext都有一个ObjectContext。 但我经常得到“IEntityChangeTracker”exception,因此它可能无法正常工作:

// 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的多个实例引用”exception?

编辑:显示如何处置ObjectContext:

 // in HttpRequestModule.cs private void Application_EndRequest(object source, EventArgs e) { ServiceLocator.Current.GetInstance().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(); } } 

我的猜测是你已经在内存中存储了一个对象(很可能是使用进程内模式的http缓存,但也可能是任何手动缓存,如共享字典),现在你已经以某种方式将该对象与某个东西相关联否则,例如:

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

因此,如果缓存的对象仍然认为它附加到上下文,则会出现问题; 不仅如此,您可能会意外地保留整个图表。


代码看起来没问题(只要你在请求结束时处理它),但这是添加的好时机:

 private const string EFContextKey = "EF.ObjectContext"; 

并使用它代替5文字。 避免一些风险; p