代码之家  ›  专栏  ›  技术社区  ›  Eoin Campbell

Entity Framework 6正在重新加载(重新延迟加载)以前使用include()水合的子集合

  •  1
  • Eoin Campbell  · 技术社区  · 7 年前

    我们在过去的几天里发现了一个奇怪的错误。

    简而言之,Entity Framework似乎正在尝试延迟加载一个集合,该集合以前是通过使用 Include() )结果是 ObjectContextDisposed 例外

    我们有一个非常简单的2实体模型,代表零售商及其网站支持的多对多配置语言。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作为 InstancePerRequest
    2. API调用请求缓存所有零售商

      1. 如果缓存中有数据,而缓存过期时间尚未过期,它将返回 List<Retailer> 从缓存中
      2. 如果缓存没有数据或缓存过期,它将运行以下查询来刷新缓存并将其返回给用户。

      //让所有零售商,急切地加载他们的语言子集合 上下文 .零售商 .包括(r=>r.语言) .托利斯特();

    我们现在看到的是,在一段时间后,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的某些内部部分决定语言代理集合不再有效,需要重新加载/重新延迟加载。

    我们可以在这里做一些不同的事情:

    • 缓存DTO而不是EF实体
    • 迭代结果并使用 dbContext.Entry(entity).State = EntityState.Detached; 拆开每一个
    • 试着打电话 AsNoTracking 关于我们的问题

    但我们在这里对EF都很有经验,并且已经使用了多年,所以我们有点困惑为什么会发生这种情况。EntityFramework是否会在任何情况下尝试重新加载之前已加载的集合 包括()

    0 回复  |  直到 7 年前