3

我对某个父实体 ( Order) 有一个查询,我想急切地加载它的一些子集合或属性。我有一个这样的查询:

public void QueryMethod()
{
    using (var context = new MyContext())
    {
        var orders = context.Order.Include("OrderProduct")
                                  .Include("OrderProduct.ProductVariant")
                                  .Where(some query)
                                  .ToList();
    }
}

我正在做的是遍历这个订单集合,并为每个Order我到达的OrderProduct属性ProductVariant。当上下文处于活动状态时,我可以在查询方法中执行此操作。但是当我尝试ProductVariant.OrderProduct在上下文之外访问时,我得到ObjectDisposedException.

顺便说一句,我试图访问ProductVariant.OrderProduct一些奇怪的原因。我认为我不应该这样访问它,但我的意思是我可以从OrderProductto到达ProductVariant,但我不能从ProductVariantto访问OrderProduct。我想知道为什么我会收到这个错误,尽管我添加OrderProduct.ProductVariant了我的急切加载属性。它不应该双向工作吗?

任何帮助将不胜感激。

4

1 回答 1

1

您获得ObjectDisposedException上下文之外的事实表明 Entity Framework 尝试ProductVariant.OrderProduct通过延迟加载从数据库中加载所引用的对象。

现在,这并不一定意味着——而且这个说法听起来很奇怪——它还ProductVariant.OrderProduct没有加载并填充正确的实体。可能是这样,因为它只是OrderProduct.ProductVariant通过预先加载加载的逆属性。对于一对一和一对多关系,EF 将在加载导航属性时自动填充反向导航属性(“关系修复”)。

尽管填充了反向导航属性,但不一定将其标记为已加载,这是由每个导航属性的上下文维护的标志,它告诉 EF 当您在代码中访问导航属性时,是否必须通过延迟加载从数据库加载导航属性.

例如,对于一对多关系,很容易看出,当导航属性由于关系修复而被填充时,EF 不得将其标记为已加载。例如:如果您加载包含其客户参考的订单context.Orders.Include("Customer").Single...-Orders急切加载的客户中的集合将包含此加载的订单(因为关系修复)。但是这个单一的订单很可能不是这个客户的唯一订单(或者至少 EF 不知道这是唯一的订单还是数据库中是否还有更多订单)。如果您访问该Customer.Orders集合,您通常希望不仅返回该单个订单,而且返回客户的所有订单 - 换句话说,您希望发生延迟加载查询,该查询会从数据库加载客户的其余订单。

现在,这个论点对于一对一的关系并不真正令人信服,因为对于这种关系,很明显数据库中不能有多个相关对象。那么,如果这个单一的相关对象已经加载,为什么 EF 要运行延迟加载查询呢?

我不知道为什么 EF 仍然尝试为一对一关系加载反向导航属性,但在这方面它可能只是不区分一对多和一对一关系. 也许 EF 遵循一般规则,即如果关系的主体由关系修复填充,则它不会被标记为已加载,并且在您访问它时无论如何都会发生延迟加载。(我无法从您的代码片段中真正看出是否OrderProduct或是ProductVariant主体,这只是一个猜测。)

无论如何,在您的情况下,我会禁用延迟加载甚至代理创建(包括禁用延迟加载),因为您在块Include内使用using并且延迟加载在这里没有任何好处。您遇到的异常应该消失:

using (var context = new MyContext())
{
    context.Configuration.ProxyCreationEnabled = false;

    var orders = context.Order.Include("OrderProduct")
                              .Include("OrderProduct.ProductVariant")
                              .Where(some query)
                              .ToList();
}
于 2013-09-27T18:54:36.263 回答