使用实体框架如何在没有一个庞大查询结果集或数百个小型查询的情况下创建嵌套对象?

2024-05-01

我使用 EF 填充对象,然后在业务层代码中与之交互。这些对象有多个级别,但我们首先将其简化为典型的主从示例Order and OrderLine.

假设我需要检索 50 个订单,每个订单大约有 100 个订单行,并且我需要所有这些数据。在 EF 中执行此操作最有效的方法是什么?

如果我这样做:

var orders = context.Orders.Where(o => o.Status == "Whatever")
                .Include(order => order.OrderLines)
                .ToList();

然后它会运行一个查询来拉回 50x100 行,然后它巧妙地将其组装成 50Order对象,每个对象都有自己的OrderLine对象。

如果我不这样做Include()然后我会迭代每个Order和它的OrderLines,然后它将发出 50 个单独的查询来获取OrderLine数据,即每个数据一个Order.

到目前为止.Include()看起来很棒:我从 SQL 中提取了比需要的多一点的数据,但这比发出 50 个额外查询要好得多。但是有没有一种方法可以让我选择发出 2 个查询,其中一个是获取Order和一个得到OrderLine,并且 EF 自动连接对象?

我想要的一个更现实的场景是数据更复杂。假设我想要这样的对象(其中Product是在 购买的东西OrderLine and ProductPart是用于制作的位数Product):

- Order
   - OrderLine (avg 100 per Order) 
       - Product (1 per OrderLine)
           - ProductPart (avg 20 per Product)

现在如果我做一个.Include() with ProductPart,它会让查询结果变得更大。或者如果我不这样做Include()然后它会为每个发出单独的查询Product.

有没有第三种方法可以让我获得所有Order, OrderLine and Product一次查询中的数据以及所有ProductPart另一个查询中的数据,并且 EF 神奇地为我连接对象?

UPDATE:

我刚刚读到AsSplitQuery() https://learn.microsoft.com/en-us/ef/core/querying/related-data这似乎是我正在寻找的东西,但仅在 EF Core 5 中可用,该版本直到 2020 年 11 月才稳定(?)。我正在寻找一种在 EF6 中实现此目标的方法。

更多研究,我发现https://entityframework.net/improve-ef-include-performance https://entityframework.net/improve-ef-include-performance当父对象有多个对象类型时,建议采用两种方法:

  1. 执行多个EF命令拉回相同的父对象列表,但是每次Include()- 不同的子对象类型。显然,EF 将连接它已经从数据库中提取的相关对象。

  2. 使用 EF+ 库,它似乎可以做类似的事情AsSplitQuery()

我不确定这是否适用于我的情况,即有更多级别的嵌套,而不仅仅是父对象之外的不同类型的对象。如果我聪明的话,我的猜测是肯定的。有小费吗?


像这样的事情可能会稍微破坏您的对象结果,但应该执行两个单独的查询。

var ordersQuery = context.Orders.Where(o => o.Status == "Whatever");

var orderLineGroups = ordersQuery
   .SelectMany(o => o.OrderLines)
   .ToLookup(l => l.OrderID); // <- Not sure what your FK name is

var orders = ordersQuery.Select(o => new {
   Order = o,
   OrderLines = orderLineGroups[o.Id]
}).ToList();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用实体框架如何在没有一个庞大查询结果集或数百个小型查询的情况下创建嵌套对象? 的相关文章

随机推荐