C # Entity Framework, используя только один ObjectContext на HttpContext - PullRequest
5 голосов
/ 14 июля 2011

В ASP.NET MVC 2, используя Entity Framework 4, я получаю эту ошибку «На объект сущности нельзя ссылаться несколькими экземплярами IEntityChangeTracker».

Поиск SO показывает, что это, вероятно,потому что у меня есть разные экземпляры Entity Framework ObjectContext, когда это должен быть только один экземпляр ObjectContext для каждого HttpContext.

У меня есть этот код (написанный задолго до того, как я присоединился), который, кажется, делает именно это - имеет один ObjectContextза каждый HttpContext.Но я получаю исключение "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;
}

Я изучил этот код, и он выглядит правильно.Насколько я могу сказать, он возвращает один экземпляр ObjectContext для каждого HttpContext.Код неправильный?

Если код не является неправильным, почему бы мне не получить ссылку «Объект сущности не может быть указан несколькими исключениями 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();
    }
}

1 Ответ

5 голосов
/ 14 июля 2011

Я предполагаю, что вы сохранили объект где-то в памяти (скорее всего, это кеш 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...