繁体   English   中英

实体框架条件选择

[英]Entity Framework Conditional Selection

编号1 编号2 日期 State
1个 1个 2022-03-14 失败的
1个 1个 2022-03-15 成功

鉴于上面的数据库表,我正在尝试编写 EF 查询,我们在其中显示每个 Id Id2 组合的最新记录,但失败将永远列出。 仅当成功发生在上周时才会包括在内。

我认为我正在努力解决的部分是,如果给定的 Id Id2 组合存在失败,但未来会成功,则不应返回失败。

关于从哪里开始的任何建议? 之前的尝试试图做一个

.Where(x => x.state == 'Failed' || x.CreatedOn > DateTime.Now.AddDays(-7)

但是列出了 10 天前的失败和 9 天前的成功。 (这个案例应该不会返回任何东西,因为成功是在一个多星期前)

基本上都失败了,除了后来成功的 UNION 成功持续了 2 天。 这可能吗? 我从来没有在两张桌子之间的 linq 上花这么长时间。

先问一个问题:如果最新的state失败了,是不是只想报上次成功之后的失败? 换句话说,对于序列 {Failure, Failure, Success, Failure, Failure} 你只想报告最后两个失败吗? 我会假设,是的。

在我看来,您首先需要按 Id2 分组并为每个组计算两件事:

  1. 最新的是什么 state。
  2. 最近成功的日期是什么时候。

从那里,您可以 select 组的成员,其中:

  1. LatestState = "Success" 和 Date = LatestSuccessDate,或
  2. State =“失败”和(LatestSuccessDate 为 null 或日期 > LatestSuccessDate)

就像是

Data
    .Where(r => r.CreatedOn >= DateTime.Now.AddDays(-7))
    .GroupBy(r => r.Id2)
    .SelectMany(grp => new {
        var latestState = grp
            .OrderByDescending(r => r.CreatedOn)
            .Select(r => r.State)
            .First(),
        var latestSuccessDate = grp
            .OrderByDescending(r => r.CreatedOn)
            .Where(r => r.State = 'Success')
            .Select(r => r.CreatedOn)
            .FirstOrDefault();
        return grp
            .Where(r =>
                (latestState == "Success" && r.CreatedOn == latestSuccessDate)
                || (r.State == "Failure" && (latestSuccessDate == null || r.CreatedOn > latestSuccessDate))
            );
    });

免责声明 - 以上未经检查,在语法上可能不是 100% 正确,但传达了我的想法。 我确信还有优化的空间,例如预先订购每个组的成员。

我希望上面的代码将执行 memory 中的大部分工作。我不确定是否可以将其编码为将转换为服务器端 SQL 查询的形式。 比我有更多技能的人可能会提供解决方案。 目标是生成如下内容:

SELECT D.*
FROM (
    -- Select latest state per group
) LS
LEFT JOIN (
    -- Select the latest success date per group
) LSD
    ON LSD.Id2 = LS.Id2
JOIN DATA D
    ON D.Id2 = LS.Id2
WHERE -- Other conditions 

我不确定这是否可以转换为 EF 查询,但我认为我会发布它以防万一(或者万一它可以提供一些灵感)。 这是一个 Linq 到对象的方法,应该产生所需的 output。

如果你的class定义如下:

public class Item
{
    public int Id1 { get; set; }
    public int Id2 { get; set; }
    public DateTime Date { get; set; }
    public State State { get; set; }
}

public enum State
{
    Undefined,
    Success,
    Failed
}

并且您的项目存储在Item集合中,您可以:

  1. Id1Id2对项目进行分组
  2. 从每组中,select 具有最新Date值的一项(使用.MaxBy()
    • .MaxBy( * )也可以替换为.OrderByDescending( * ).First()
  3. 过滤现在不同的Id1Id2项目集合以仅保留具有State = Failed或不少于一周的项目

对于项目集合List<Item> items ,它可以实现如下:

List<Item> result = items
    .GroupBy(item => ( item.Id1, item.Id2 ))
    .Select(gr => gr.MaxBy(item => item.Date))
    .Where(item =>
          item.State == State.Failed ||
          item.Date > DateTime.Now.AddDays(-7))
    .ToList();

示例小提琴在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM