C# Entity Framework using only one ObjectContext per HttpContext

天涯浪子 提交于 2019-11-29 21:26:20

问题


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".

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.

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;
}

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?

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

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

回答1:


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";

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



来源:https://stackoverflow.com/questions/6688772/c-sharp-entity-framework-using-only-one-objectcontext-per-httpcontext

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!