C# 实体框架每个 HttpContext 仅使用一个 ObjectContext
Posted
技术标签:
【中文标题】C# 实体框架每个 HttpContext 仅使用一个 ObjectContext【英文标题】:C# Entity Framework using only one ObjectContext per HttpContext 【发布时间】:2011-10-05 01:12:25 【问题描述】:在 ASP.NET MVC 2 中,使用 Entity Framework 4,我收到此错误“一个实体对象不能被多个 IEntityChangeTracker 实例引用”。
搜索 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();
【问题讨论】:
您是否在 EndRequest 方法中处理上下文? 更新显示处理方法 【参考方案1】:我的猜测是您已经在内存中的某个位置存储了一个对象(很可能是使用进程内模式的 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
【讨论】:
实际上我已经在缓存中存储了一个对象(Currency DefaultCurrency),然后将其附加到订单对象(order.Currency = DefaultCurrency) - 这正是引发异常的地方.. 那是很有前途的铅。当我将 DefaultCurrency 保存到缓存时,它的类型是System.Data.Entity.DynamicProxies.Currency_F4008E27DE_etc
,而不是 POCO 类 Entities.Currency
。我需要对这个对象做什么才能安全地将其存储在缓存中,然后稍后将其添加到另一个对象中,然后将其分离?
@JK - 棘手;因为可能有多个线程试图同时使用它,所以我建议的最好的事情是编写一些克隆它的代码(创建一个不附加到上下文的 vanilla POCO),然后 store 一个克隆(避免保持图表存活的风险),并在每次取出它时再次克隆它。我不知道在 EF 中是否可行,但如果这是 L2S,我会设置 DefaultCurrencyId
而不是 DefaultCurrency
- 避免一些问题情况。
谢谢,我会看看我能做些什么以上是关于C# 实体框架每个 HttpContext 仅使用一个 ObjectContext的主要内容,如果未能解决你的问题,请参考以下文章