【问题标题】:How to JOIN a Sub-Query using LINQ如何使用 LINQ 加入子查询
【发布时间】:2020-11-30 04:18:08
【问题描述】:

我是 Entity Framework 和 LINQ 的新手,正在努力将我的 SQL 查询“转换”为其语法。

Given 是一个表格,其中包含以OrderNumberQuantityMaterial 等为列的生产订单。另外还有一列Timestamp

如果要更新订单的数量,则会在表中产生一个全新的条目,其中所有值都将与前一行相同,除了Timestamp(表示更改时间)和@987654327 @(包含新值)。从而让我有一个订单的“历史”。

使用 SQL 仅选择特定订单的最新版本可能如下所示:

SELECT p1.*
FROM dbo.ProductionOrders as p1
  JOIN (SELECT OrderNumber, MAX(Timestamp) as Timestamp FROM dbo.ProductionOrders GROUP BY OrderNumber) as p2
    on p1.OrderNumber = p2.OrderNumber and p1.Timestamp = p2.Timestamp
WHERE p1.OrderNumber = 'order-182736'

与我在 C# 代码中完成的功能相同,如下所示:

var productionOrder = _db.ProductionOrders.Where(po => po.OrderNumber == "order-182736")
                                          .OrderByDescending(po => po.Timestamp)
                                          .FirstOrDefault();

当我想获得多行时,我迷路了。例如,特定材料的所有订单。使用 SQL 我只需要调整WHERE 条件:

SELECT p1.*
FROM dbo.ProductionOrders as p1
  JOIN (SELECT OrderNumber, MAX(Timestamp) as Timestamp FROM dbo.ProductionOrders GROUP BY OrderNumber) as p2
    on p1.OrderNumber = p2.OrderNumber and p1.Timestamp = p2.Timestamp
WHERE p1.Material = 42

我使用 LINQ 为 JOIN 找到的示例不会对子查询进行操作(我的主要来源是 microsoft.com

如何使用 LINQ 获取特定材料的所有最新“版本”订单?

【问题讨论】:

    标签: linq .net-core entity-framework-core


    【解决方案1】:

    您可以按照与 SQL 完全相同的方式进行操作。 LINQ to Entities 中的 _db.ProductionOrders 代表SQL 中的dbo.ProductionOrders,您可以在顶级和子查询级别使用它:

    var query = _db.ProductionOrders
        .Join(_db.ProductionOrders
            .GroupBy(p2 => new { p2.OrderNumber })
            .Select(g => new { g.Key.OrderNumber, Timestamp = g.Max(e => e.Timestamp) }), // subquery
            p1 => new { p1.OrderNumber, p1.Timestamp }, p2 => p2, // join condition
            (p1, p2) => p1) // result selector (p1.*)
        .Where(p1 => p1.Material == 42);
    

    (注意:不确定Label 在您的 SQL 查询中来自何处,因此请改用OrderNumber)。

    或者,如果您愿意,也可以使用 LINQ 查询语法:

    var query =
        from p1 in _db.ProductionOrders
        join p2 in (from p2 in _db.ProductionOrders
                    group p2 by new { p2.OrderNumber }) into g
                    select new { g.Key.OrderNumber, Timestamp = g.Max(p2 => p2.Timestamp) })
        on new { p1.OrderNumber, p1.Timestamp } equals p2
        where p1.Material == 42
        select p1;
    

    【讨论】:

    • Label 仍然存在,因为我犯了一些复制和粘贴错误,我更改了 OP。我需要一些时间来了解一下 LINQ...
    猜你喜欢
    • 1970-01-01
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    相关资源
    最近更新 更多