8

我正在编写一个查询SelectMany并检查它在 LINQPad 中生成的 SQL。查询非常简单。

假设我有 3 个实体:Customer, Order, OrderItem. OrderItem保存有关订购什么产品和数量的信息。

我想OrderItems为一个客户得到所有。

context.Customers.First().Orders.SelectMany(o=>o.OrderItems)

我得到了我期望的结果集,但 SQL 对我来说真的很奇怪。有一堆选择语句。首先它选择一个客户,这没关系。然后它选择一个订单(因为这个客户只有一个),然后为OrderItem之前选择的每个订单创建一个选择Order......所以我得到的选择数量与 selected的OrderItems+一样多。所以它看起来像:OrdersCustomer

select top 1 from Customers;

select * from Orders where CustomerID = @cID;

select * from OrderItems where OrderID = @o1;
select * from OrderItems where OrderID = @o2;
select * from OrderItems where OrderID = @o3;
select * from OrderItems where OrderID = @o4;

我期望的是这样的:

select oi.* 
from OrderItems oi
join Orders o on o.OrderID = oi.OrderId
join Customers c on c.CustomerID = o.CustomerID
where c.CustomerID = @someID

一个选择,漂亮干净。

SelectMany真的像那样工作还是我做错了什么,或者我的模型有问题?我找不到任何关于这种简单SelectMany应该如何转换为 SQL 的示例。

这对于小数字无关紧要,但是当客户有 100 个订单,每个订单有 200 个订单项目时,就会有 20 000 个选择......

4

1 回答 1

9

您应该使用以下内容进行查询(使用 查询特定客户的订单商品someId):

context.Customers.Where(c => c.Id == someId)
    .SelectMany(c => c.Orders.SelectMany(o => o.OrderItems))

或者 - 重现First()但使用单个数据库查询的行为:

context.Customers.Take(1)
    .SelectMany(c => c.Orders.SelectMany(o => o.OrderItems))

您的原始查询使用First(查询 1)加载客户,然后延迟加载加载该Orders客户的集合(查询 2),然后延迟加载再次加载每个加载的订单项目集合Order(查询 3 到 n)。为避免所有这些多个查询,您不得在查询表达式中使用“查询执行方法”,例如First()orToList()等​​。

于 2012-12-05T13:30:35.917 回答