实体框架 - Linq GroupBy 来自多个表的数据



我想按 Order.CustomerID 对数据进行分组(以罗斯文为例)。

在SQL中,它看起来像这样:

Select
o.CustomerID,
SUM(od.Quantity * od.UnitPrice * (1-od.Discount))
FROM Orders o INNER JOIN [Order Details] od ON o.OrderID = od.OrderID
GROUP BY o.CustomerID

如何使用 Linq 加载该数据?

我试过了

var order = context.Customers.Include("Orders.Order_Details")
.SelectMany(x => x.Orders)
.Select(x => new
{
Customer = x.Customer,
Sum = x.Order_Details.Sum(y => (float)(y.Quantity * y.UnitPrice) * (1 - y.Discount))
})
.GroupBy(x => x.Customer)
.Select(x => new
{
x.Key.CompanyName,
Sum = x.Sum(y => y.Sum)
});

但是生成的查询很丑陋且太长。 任何帮助将不胜感激。

我认为您不需要分组,因为所有实体都已链接:

context.Customers.Include("Orders.Order_Details").
Select(c => new
{
Customer = c,
Total = c.Orders.SelectMany(o => o. Order_Details).
Sum(d => d.Quantity * d.UnitPrice * (1-d.Discount))
});

显然,客户和订单之间存在一对多关系:每个客户都有零个或多个订单,每个订单只属于一个客户。

订单和订单详细信息之间也存在一对多关系:每个订单都有零个或多个订单详细信息,并且每个订单详细信息只属于一个订单。

此外,订单明细具有数量,单价和折扣。

现在,给定您的 SQL 语句,您希望将所有订单分组为同一客户的订单组。从每个组中,您需要CustomerId,以及该组中所有订单的所有订单详细信息的价格总和。

有几种方法可以使用 LINQ 执行此操作。您尝试从所有客户开始:

var totalOfAllOrdersOfCustomers = dbContext.Customers
.Select(customer => new
{
CustomerId = customer.Id,
TotalAllOrders = customer.Orders
.SelectMany(order => orderDetails)
.Select(orderDetail => orderDetail.Quantity * orderDetail.UnitPrice
* (1-orderDetail.Discount))
.Sum();
}

用一句话说:从每个客户那里拿走ID。同时获取此客户的所有订单的所有订单详细信息 (=SelectMany)。从每个订单详细信息中,使用公式计算价格,并将所有这些价格相加。

这将提供与您的 SQL 查询非常相似的东西。但是,有一个区别:如果您的客户没有任何订单,您仍然会获得一条带有 CustomerId 和等于零的总和的记录。

如果这是您想要的,则应使用此方法。

为了获取没有任何订单的客户,SQL 将在内部从客户表与订单表进行左外连接。您无法仅通过查看订单表来查找没有订单的客户。

您的 SQL 语句表明您不希望客户没有任何订单。如果是这种情况,则不必使用"客户"表来获取结果:

var totalOfAllCustomersThatHaveOrders = dbContext.Orders
.GroupBy(order => order.CustomerId)
.Select(group => new
{
CustomerId = group.Key,
TotalAllOrders = group.SelectMany(group.OrderDetails)
.Select(orderDetail => orderDetail.Quantity * orderDetail.UnitPrice
* (1-orderDetail.Discount))
.Sum();
}

换句话说:接受所有订单。将它们放入具有相同客户 ID (=GroupBy) 的订单组中。从每个组中获取Key(这是组中所有订单的客户 ID)并将其分配给客户 ID。第二部分类似于第一个解决方案:从该组(=SelectMany)中的所有订单中获取所有订单详细信息,并根据公式计算订单详细信息的价格。最后,对所有这些价格求和,并将此总和分配给总订单

因此,第一个需要额外的左外连接,因为它为您提供了没有订单的客户。第二个稍微简单一些,但如果不会给你还没有订购任何东西的客户。

请注意,在您的最终结果中,您只知道您的客户是 ID。如果您在此语句之后立即获取一些客户数据("哦,现在我有了 CustomerId,我想要客户名称和地址"),我将使用第一种方法,从"客户"表开始,然后选择所需的所有客户属性。这将为您节省一次数据库往返。

最新更新