我们在过去的几天里发现了一个奇怪的错误。
简而言之,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的内存缓存中。
-
ApplicationContext作为
InstancePerRequest
-
API调用请求缓存所有零售商
-
如果缓存中有数据,而缓存过期时间尚未过期,它将返回
List<Retailer>
从缓存中
-
如果缓存没有数据或缓存过期,它将运行以下查询来刷新缓存并将其返回给用户。
//让所有零售商,急切地加载他们的语言子集合
上下文
.零售商
.包括(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是否会在任何情况下尝试重新加载之前已加载的集合
包括()