简体   繁体   English

实体框架5急切加载父属性

[英]Entity Framework 5 eager loading with parent properties

I have a query on some parent entity ( Order ) and I want to load some of its sub collections or properties eagerly. 我有一些父实体( Order )的查询,我想热切地加载它的一些子集合或属性。 I have a query like this: 我有这样的查询:

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

What I am doing is I loop through this order collection and for each Order I reach to OrderProduct and ProductVariant properties. 我正在做的是循环遍历此订单集合,对于每个Order我都会访问OrderProductProductVariant属性。 I can do this inside the query method, when the context is alive. 当上下文处于活动状态时,我可以在查询方法中执行此操作。 But when I try to access ProductVariant.OrderProduct outside the context, I get ObjectDisposedException . 但是当我尝试在上下文之外访问ProductVariant.OrderProduct ,我得到了ObjectDisposedException

By the way, I am trying to access to ProductVariant.OrderProduct for some weird reason. 顺便说一下,我试图访问ProductVariant.OrderProduct有一些奇怪的原因。 I think I shouldn't access it like this but my point is that I can reach from OrderProduct to ProductVariant , but I can't access from ProductVariant to OrderProduct . 我想我不应该这样访问它,但我的观点是我可以从OrderProductProductVariant ,但是我无法从ProductVariant访问OrderProduct I am wondering why I get this error despite that I added OrderProduct.ProductVariant into my eager loading properties. 我想知道为什么我得到这个错误,尽管我将OrderProduct.ProductVariant添加到我的渴望加载属性中。 Isn't it supposed to work both ways? 它不应该双向工作吗?

Any help will be very much appreciated. 任何帮助将非常感谢。

The fact that you get an ObjectDisposedException outside the context indicates that Entity Framework tries to load the object that ProductVariant.OrderProduct is refering to via lazy loading from the database. 您在上下文外部获得ObjectDisposedException这一事实表明Entity Framework尝试通过数据库中的延迟加载来加载ProductVariant.OrderProduct引用的对象。

Now, this doesn't necessarily mean - and this statement sounds odd - that ProductVariant.OrderProduct isn't already loaded and filled with the correct entity. 现在,这并不一定意味着 - 这个陈述听起来很奇怪 - ProductVariant.OrderProduct尚未加载并填充正确的实体。 Probably it is, because it's just the inverse property of OrderProduct.ProductVariant which you have loaded via eager loading. 也许这是因为它的是相反的属性OrderProduct.ProductVariant通过预先加载加载。 For one-to-one and one-to-many relationships EF will populate the inverse navigation properties automatically when a navigation property is loaded ("Relationship fixup"). 对于一对一和一对多关系,EF将在加载导航属性时自动填充反向导航属性(“关系修正”)。

Despite the inverse navigation property is populated it isn't necessarily marked as loaded which is a flag maintained by the context per navigation property that tells EF if a navigation property has to be loaded from the database via lazy loading when you access it in your code. 尽管填充了反向导航属性,但它不一定标记为已加载 ,这是由每个导航属性的上下文维护的标志,它告诉EF当您在代码中访问它时是否必须通过延迟加载从数据库加载导航属性。

For a one-to-many relationship for example it is easily seen that EF must not mark a navigation property as loaded when it gets populated due to relationship fixup. 例如,对于一对多关系,很容易看出EF由于关系修正而在填充时不得将导航属性标记为已加载。 For instance: If you load an order including its customer reference - context.Orders.Include("Customer").Single... - the Orders collection in the eagerly loaded customer would contain this loaded order (because of relationship fixup). 例如:如果您加载包含其客户引用的订单 - context.Orders.Include("Customer").Single... - 急切加载的客户中的Orders集合将包含此加载的订单(因为关系修正)。 But this single order is most likely not the only order that this customer has (or at least EF cannot know if that's the only order or if there are more in the database). 但是这个单一订单很可能不是该客户唯一的订单(或者至少EF不知道这是唯一订单还是数据库中有更多订单)。 If you access the Customer.Orders collection you usually expect that not only this single order is returned but all orders of the customer - in other words, you expect that a lazy loading query happens that loads the rest of the customer's orders from the database. 如果您访问Customer.Orders集合,您通常期望不仅返回此单个订单而且还返回客户的所有订单 - 换句话说,您希望发生延迟加载查询,从数据库加载客户的其余订单。

Now, this argument isn't really convincing for a one-to-one relationship because for such a relationship it is clear that there can't be more than one related object in the database. 现在,这个论点并不能真正说服一对一的关系,因为对于这种关系,很明显数据库中不能有多个相关对象。 So, why would EF want to run a lazy loading query if this single related object is already loaded? 那么,如果已经加载了这个单个相关对象,为什么EF想要运行延迟加载查询?

I don't know why EF still tries to load the inverse navigation property for the one-to-one relationship, but possiby it just doesn't distinguish between a one-to-many and a one-to-one relationship in this respect. 我不知道为什么EF仍然试图为一对一关系加载逆导航属性,但是在这方面它只是不区分一对多关系和一对一关系。 Maybe EF follows the general rule that if the principal side of the relationship is populated by relationship fixup it isn't marked as loaded and lazy loading will happen in any case when you access it. 也许EF遵循一般规则,即如果关系的主要方面由关系修正填充,则它不会被标记为已加载,并且在您访问它时,任何情况下都会发生延迟加载。 (I can't really see from your code snippet if OrderProduct or ProductVariant is the principal, it is just a guess.) (我无法从你的代码片段中看到,如果OrderProductProductVariant是主体,那只是猜测。)

Anyway, in your situation I would disable lazy loading or even proxy creation (which includes disabling lazy loading) because you're using Include inside a using block and lazy loading has no benefit here. 无论如何,在你的情况下,我会禁用延迟加载甚至代理创建(包括禁用延迟加载),因为你在using块中使用Include并且延迟加载在这里没有任何好处。 The exception you are having should disappear then: 你所拥有的例外应该会消失:

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

    var orders = context.Order.Include("OrderProduct")
                              .Include("OrderProduct.ProductVariant")
                              .Where(some query)
                              .ToList();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM