LINQ-Entity Framework Core-仅在满足其他条件的情况下才选择最新记录

问题描述 投票:0回答:2

我有一个看起来像这样的数据集。我想选择节点最近记录的状态为“待处理”的所有行]

Nodeid  Status     Type          Utctimestamp
------  -----      ------        --------   

1       Pending    Transaction   2020-03-13 03:31:00.00000+00
1       Overridden Transaction   2020-03-13 03:32:00.00000+00
2       Unknown    Other         2020-03-13 03:34:00.00000+00
2       Pending    Other         2020-03-13 03:35:00.00000+00

仅当最新记录的状态为Pending时,才应返回每个节点的记录(否则,不要为该节点选择任何内容)。因此,对于上面的数据集,查询将仅返回以下内容:

2       Pending    Other         2020-03-13 03:35:00.00000+00

我想使用流利的语法(“方法语法”)在Entity Framework中使用LINQ查询。我该怎么办?

entity-framework-core linq-to-entities
2个回答
0
投票
[如果您希望最新的节点记录具有待处理状态,并且假定您可以将一个节点多次切换到“待处理”,即]]

node ID Status Time 1 Pending xxxx 1 Submitted xxxy 1 Pending xxxz

您想在时间行“ xxxz”的地方:

使用EF6

string pendingStatus = Status.Pending.ToString(); var pending = myContext.TransactionMsg .Where(x => x.Status == pendingStatus) .GroupBy(x => x.NodeId) .Select(g => g.OrderByDescending(x => x.UtcTimestamp).FirstOrDefault()) .ToList();

现在我无法在EF Core上使用它(惊喜,令人惊讶),因此,如果您在使用Core,则需要进行一些挖掘,以找出如何解决它似乎无法解决的问题。从组表达式中选择OrderByDescending。坚持使用EF 6的另一个理由:)

更新:好的,基于仅获取最新状态为待决节点的要求。通过将Where子句移到Select之后,在EF6中获得此相对简单。

在EF Core中执行此操作要困难得多,但看起来确实可行。最大的问题是如何在EF Core中实现GroupBy。关于如何与IGrouping结果进行交互的更多限制,其中EF6可以成功地将它们作为一组进行平移/交互,而EF Core将尝试将OrderBy和此类表达式与分组结果一起使用的情况除外。因此,您需要更加详细:

var results = context.Nodes .GroupBy(x => x.NodeId, (x,y) => new { Timestamp = y.Max(z => z.Timestamp), NodeId = x }) .Join(context.Nodes, a => new { a.NodeId, a.Timestamp }, b => new { b.NodeId, b.Timestamp }, (a,b) => b) .Where(g => g.Status == "Pending") .ToList();

这看上去确实很烂,但是快速浏览一下:我们首先按Node ID对节点进行分组,然后从中选择Max(相对于分组结果)使用最新的Timestamp,以获得最大的Timestamp,然后使用分组的Key选择Node ID。这给出了{ Timestamp (max row), NodeId }的结构。使用此,我们Join返回到Nodes集合,使用Node ID和Timestamp的键比较将我们选择的结果与Nodes集合配对,以便我们可以将这些分组的项目转换回Node实体。这将返回与节点ID和最大时间戳匹配的节点集合,即“最新节点”。从中,我们应用Where子句仅选择处于“待处理”状态的最新节点。 

0
投票
我是这样实现的:
© www.soinside.com 2019 - 2024. All rights reserved.