正如我在问题Eagerly Load Navigation Property that is List<OfSomeBaseClass>
中发现的那样,无法使用EF .Include()
方法加载派生类的属性(这已经是suggested as a future EF feature)。
我通过迭代包含混合兄弟类型的集合来解决这个问题,单独调用
ctx.Entry(myDerivedType).Reference("PropOfDerivedType").Load();
这会导致许多额外的往返数据库,但至少它可以工作。
现在我需要加载这样的对象层次结构并将其保存在MVC Web应用程序的Session中。由于DbContext
不应该是会话的一部分,我相信我必须加载对象图AsNoTracking()
,如下所示:
var myGraph = (from my in ctx.MyHierarchyRoot.Include("NonDerivedStuff")
.AsNoTracking()
where CONDITION select my).Single();
问题1
如果要将对象图存储在Session中,是否有必要使用.AsNoTracking()
?
然后我继续遍历层次结构中的派生兄弟,并尝试像这样加载它们:
foreach (SomeBase b in myGraph.SomeCollection)
{
if (b is SomeConcreteDerivedType)
{
ctx.Entry(b).Reference("SomePropertyOfSomeConcreteDerivedType").Load();
}
}
但是,由于我使用.AsNoTracking()
加载myGraph,我得到:
无法为属性调用成员'加载' 'SomePropertyOfSomeConcreteDerivedType'因为实体的类型 上下文中不存在“SomeConcreteDerivedType”。添加一个 实体向上下文调用Add或Attach方法 DbSet。
问题2
假设问题1的答案为“是”,我该如何正确加载派生类型的导航属性?
答案 0 :(得分:2)
如果要将对象图存储在Session中,是否有必要使用
.AsNoTracking()
?
有必要确保存储在会话中的实体不包含对上下文的任何引用(并且不需要上下文)。这应该通过在将实体保存到会话之前分离实体来执行,但是分离总是会断开关系。在这种情况下,最简单的解决方法是禁用代理创建(延迟加载和动态更改跟踪不起作用)。
替代方法是以正常方式加载实体图并创建图的深度克隆(序列化)。深度克隆始终与上下文完全分离,可以安全地存储在会话中。