使用EF代码将基类加载到对象层次结构中

时间:2012-05-23 21:01:27

标签: entity-framework-4 ef-code-first

正如我在问题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的答案为“是”,我该如何正确加载派生类型的导航属性?

1 个答案:

答案 0 :(得分:2)

  

如果要将对象图存储在Session中,是否有必要使用.AsNoTracking()

有必要确保存储在会话中的实体不包含对上下文的任何引用(并且不需要上下文)。这应该通过在将实体保存到会话之前分离实体来执行,但是分离总是会断开关系。在这种情况下,最简单的解决方法是禁用代理创建(延迟加载和动态更改跟踪不起作用)。

替代方法是以正常方式加载实体图并创建图的深度克隆(序列化)。深度克隆始终与上下文完全分离,可以安全地存储在会话中。

相关问题