1

正如我在我的问题Eagerly Load Navigation Property 中List<OfSomeBaseClass>发现的那样,无法使用 EF.Include()方法加载派生类的属性(这已被建议为未来的 EF 功能)。

我通过迭代包含兄弟类型混合的集合来解决这个问题,分别调用

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

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

然后我继续遍历层次结构中的派生兄弟并尝试像这样加载它们:

foreach (SomeBase b in myGraph.SomeCollection)
{
    if (b is SomeConcreteDerivedType)
    {
        ctx.Entry(b).Reference("SomePropertyOfSomeConcreteDerivedType").Load();
    }
}

但是,由于我使用 myGraph 加载.AsNoTracking(),我得到:

无法为属性“SomePropertyOfSomeConcreteDerivedType”调用成员“Load”,因为上下文中不存在“SomeConcreteDerivedType”类型的实体。要将实体添加到上下文中,请调用 DbSet 的 Add 或 Attach 方法。

问题2

假设问题 1 的答案是“是”,如何正确加载派生类型的导航属性?

4

1 回答 1

2

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

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

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

于 2012-05-24T08:58:37.170 回答