Entity Framework 6 перезагружает (повторно отложенную загрузку) подколлекции, которые ранее были гидратированы с помощью include () - PullRequest
0 голосов
/ 11 сентября 2018

У нас есть странная ошибка, которая возникла в последние пару дней.

В двух словах, Entity Framework, похоже, пытается лениво загрузить коллекцию, которая ранее была загружена (используя Include()), что приводит к ObjectContextDisposed Исключению

У нас есть очень простая модель 2 сущностей, которая представляет Retailer и Языки, которые их веб-сайт поддерживает как конфигурацию «многие ко многим».1 сайт розничной торговли может поддерживать множество языков / 1 язык может поддерживаться многими розничными продавцами.

public class Retailer
{
    public int Id {get;set;}
    public string Name {get; set;}
    public string Site {get; set;}
    public virtual ICollection<Language> Languages { get; private set; }
    //other props omitted for brevity
}

// Reciprocal class exists for Language.

Поскольку эта информация меняется не очень часто, мы кэшируем ее в кеше памяти в нашем WebAPI.

  1. ApplicationContext загружается в наш DIContainer как InstancePerRequest
  2. Вызов API запрашивает кэш для всех продавцов

  3. Если в кеше есть данные, а срок действия кеша не истек, он вернет List<Retailer> из кеша
  4. Если в кеше нет данных ИЛИ истечение срока кеша прошло, он запустит следующий запрос, чтобы обновить кеш и вернуть его пользователю.

// Получить всех розничных продавцов, желающих загрузить их контекст подколлекций Языки .Retailers .Include (r => r.Языки) .ToList ();

Теперь мы видим, что через некоторое время вызов API начнет вызывать исключение ( Экземпляр ObjectContext имеетбыл уничтожен ... ) при попытке доступа к языкам розничной торговли.

_cache.GetByKey("retailers").FirstOrDefault().Languages

System.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
   at System.Data.Entity.Core.Objects.ObjectContext.get_Connection()
   at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Load(List`1 collection, MergeOption mergeOption)
   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.DeferredLoad()
   at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject)
   at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.<GetInterceptorDelegate>b__1(TProxy proxy, TItem item)
   at System.Data.Entity.DynamicProxies.Retailer_AADFD3EC4BC12C1210279CFB5CE3F49612501FB98800B437CE0DA19DFDAF3293.get_Languages()

Кажется, что это происходит совершенно произвольно.Это похоже на то, что какая-то внутренняя часть EntityFramework решает, что коллекция языков Proxy Collection больше не действительна и должна быть перезагружена / загружена заново.

Здесь можно сделать несколько разных вещей:

  • Кэширование DTO вместо сущностей EF
  • Перебор результатов и использование dbContext.Entry(entity).State = EntityState.Detached; для отсоединения каждого
  • Попробуйте позвонить AsNoTracking по нашему запросу

Но мы все довольно опытны с EF здесь и работаем с ним годами, поэтому мы немного озадачены, почему это даже происходит.Существуют ли какие-либо обстоятельства, когда EntityFramework попытается перегрузить коллекцию, которая ранее была загружена с Include()

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