【问题标题】:LINQ statement to list orders with outstanding items to be shippedLINQ 语句列出要发货的未完成项目的订单
【发布时间】:2021-03-06 14:24:49
【问题描述】:

我在创建 LINQ 语句以选择还有待发货物品的订单时遇到问题。

简化模型如下:

销售订单
SalesOrderId (PK)

SalesOrderItem
SalesOrderItemId (PK)
描述(字符串)
SalesOrderId (FK)
产品 ID(FK)
数量(整数)

产品
产品 ID (PK)
说明
虚拟(位)

发货
ShipmentId (PK)

ShipmentItem
ShipmentItemId (PK)
SalesOrderItemId (FK)
数量(整数)

我需要一个 LINQ 语句,它生成一个销售订单列表,其中有大量待发货的物品(考虑到不需要发货的虚拟物品)。

一个销售订单可以有多个与其相关的发货。每个装运项目都与一个销售订单项目相关。

发货项目的数量与销售订单项目的数量有关。它可以是所有销售订单项目或仅部分。

已发货订单是所有订单商品均已发货的订单(订购的总数量 = 已发货的总数量)。未完成的销售订单仍有未完成的发货数量。

我不知道从哪里开始以清晰、简洁和经济的 LINQ 语句比较一个表中的数量总和。

这是实现我目标的 SQL:

SELECT a.* FROM
(
  SELECT 
    o.SalesOrderId,
    SUM(i.Qty) AS QtyOrdered,
    SUM(ISNULL(s.Qty,0)) AS QtyShipped
  FROM SalesOrder o
  INNER JOIN SalesOrderItem i ON i.SalesOrderId = o.SalesOrderId
  INNER JOIN Product p ON p.ProductId = i.ProductId
  LEFT JOIN ShipmentItem s ON s.SalesOrderItemId = i.SalesOrderItemId
  WHERE p.Virtual = 0
  GROUP BY o.SalesOrderId) a
WHERE QtyOrdered > QtyShipped

我也试过下面的 EF 语句:

var salesOrders = await _context.SalesOrder.Where(p => p.SalesOrderItems.Sum(x => x.Qty) > p.SalesOrderItems.Sum(i => i.ShipmentItems.Sum(f => f.Qty))).ToListAsync();

这会导致错误:

SqlException:无法对包含聚合或子查询的表达式执行聚合函数。无法对包含聚合或子查询的表达式执行聚合函数。

谢谢

【问题讨论】:

  • 你的简化模型太简单了。您的 SalesOrder 必须有一个销售项目列表,因为一个订单可以包含多个项目。
  • 嗨蒂姆。是的,SalesOrder 下面有一个销售订单项目表。谢谢
  • @steve_c123,也许你只是发布模型类?
  • 嗨 Svyatoslav,这些是我的简化模型类。我包含的 SQL 在使用我提供的模型类后完全实现了我的目标。我正在寻找一种使用 LINQ 实现此目的的方法。如果不可能(看起来很可能),那么我想我将需要使用原始 SQL。
  • 我还尝试使用 EF 解决这个问题。

标签: c# sql-server linq


【解决方案1】:

异常告诉您的是 EF 无法将 linq '.Sum(x => x.Qty) ' 转换为 SQL。

在这种情况下,你必须做出决定,要么

没有也永远不会有那么多数据,您将整个相关的表实体带回并在您的 .NET 运行时中计算它 - 分多个步骤在本地进行

要带回的数据太多,您最好在 SQL Server 中编写一个 SPROC 来为您执行计算,并且只将结果带回运行 .NET 的服务器,而您需要做的是仅在您的 .NET 运行时进行比较。

【讨论】:

  • 嗨,马特。感谢您的评论。我担心是这种情况。与此同时,我使用了 dapper 和我手动编写的 SQL。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多