每个HttpContext仅使用一个ObjectContext的C#实体框架 [英] C# Entity Framework using only one ObjectContext per HttpContext

查看:104
本文介绍了每个HttpContext仅使用一个ObjectContext的C#实体框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ASP.NET MVC 2中,使用实体框架4,出现此错误"IEntityChangeTracker的多个实例无法引用一个实体对象".

In ASP.NET MVC 2, using Entity Framework 4, I'm getting this error "An entity object cannot be referenced by multiple instances of IEntityChangeTracker".

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

A search of SO shows that it is probably because I have different instances of the Entity Framework ObjectContext, when it should be only one ObjectContext instance for each HttpContext.

我有这段代码(在我加入之前很久以前写的)似乎就是这样做的-每个HttpContext都有一个ObjectContext.但是我经常收到"IEntityChangeTracker"异常,因此它可能无法按预期工作:

I have this code (written long before I joined) that appears to do just that - have one ObjectContext for every HttpContext. But I am getting the "IEntityChangeTracker" exception frequently so it is probably not working as intended:

// 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实例.代码是否错误?

I've examined this code and it looks correct. It does as far as I can tell return one ObjectContext instance for each HttpContext. Is the code wrong?

如果代码没有错,为什么还要获取"IEntityChangeTracker的多个实例无法引用的实体对象"异常?

If the code is not wrong, why else would I get the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" exception?

显示如何处理ObjectContext:

To show how the ObjectContext is disposed:

// 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();
    }
}

推荐答案

我的猜测是您已将一个对象存储在内存中的某个位置(很可能是使用进程内模式的http缓存,但也可以是任何手动缓存,例如作为共享字典),现在您已将该对象与其他对象相关联,例如:

My guess is that you've stored an object somewhere in memory (most likely the http cache using in-process mode, but could also be any manual cache such as a shared dictionary), and now you've somehow associated that object with something else, for example:

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

因此,如果缓存的对象仍然认为它已附加到上下文,则会出现问题;尤其重要的是,您可能会意外地使整个图形保持活动状态.

Hence, a problem if the cached object still thinks it is attached to a context; not least, you are probably keeping an entire graph alive accidentally.

代码看起来不错(只要您在请求结束时将其丢弃),但这是添加的好时机:

The code looks OK (as long as you are disposing it at the end of the request), but this would be a good time to add:

private const string EFContextKey = "EF.ObjectContext";

,并用它代替5个文字.避免一些风险; p

and use that in place of the 5 literals. Avoids a few risks ;p

这篇关于每个HttpContext仅使用一个ObjectContext的C#实体框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆