【问题标题】:Can this LINQ query be simplified?可以简化此 LINQ 查询吗?
【发布时间】:2011-08-10 22:59:46
【问题描述】:

来自 Java,我是 C# 和 LINQ 的新手。我们的代码库中有许多查询似乎不是最佳构造的。在以下查询中,GroupBy lambda 表达式创建了一个匿名数据类型。我在网上找不到像这样使用 GroupBy 的任何示例。有没有办法简化这个查询并且仍然返回相同的结果?

 List<MachineMetrics> machines = prod.Where(p => p.TimeProduced >= start &&
                                      p.TimeProduced <= end &&
                                      (jobID == -1 ? true : (p.JobID == jobID && p.Job.MachineID == MachineID))).
                                GroupBy(x => new
                                             {
                                                 MachineName = x.Job.Machine.MachineName,
                                                 MachineID = x.Job.MachineID,
                                                 JobName = x.Job.JobName,
                                                 JobID = x.JobID
                                              }).
                                Select(item => new MachineMetrics()
                                              {
                                                 MachineName = item.Key.MachineName,
                                                 MachineID = item.Key.MachineID,
                                                 JobName = item.Key.JobName,
                                                 JobID = item.Key.JobID
                                              }).
                                ToList<MachineMetrics>();

编辑:感谢您的帮助。问题是 Equals() 和 GetHashCode() 方法没有为该类实现。一旦我添加了这些,我就使用了@Ladislav Mrnka 建议的代码,一切都按预期工作。

【问题讨论】:

  • Here is an example of GroupBy being used like this(语法不同,但结果相同)
  • 但是为什么要给变量赋值呢?链接中的示例仅显示:group x by new { x.Column1, x.Column2 }
  • 你只是在使用组来强制区分,对吧?
  • 组的目的是什么?看到你从来没有真正使用过组项目
  • @Jason - 回答您的问题“为什么要为变量赋值?” - 这是一个很好的观察。在这种情况下,这个赋值实际上是不必要的。编译器将自动将字段命名为与分配它们的属性相同的名称(在此示例中为 x.Job.Whatever),它们都是相同的名称。如果您想更改属性名称,则可以通过这种方式完成 (JobIdentifier = x.JobID)。这些名称在您的.Select() 中重复使用,它再次重新分配属性,例如:new MachineMetrics { MachineName = item.Key.MachineName

标签: .net linq entity-framework


【解决方案1】:

你正在寻找这个:

List<MachineMetrics> machines = prod.Where(p => p.TimeProduced >= start &&
                                                p.TimeProduced <= end &&
                                                (jobID == -1 || 
                                                    (p.JobID == jobID && p.Job.MachineID == MachineID))).
                                    .Select(x => new MachineMetrics()
                                          {
                                             MachineName = x.Job.Machine.MachineName,
                                             MachineID = x.Job.MachineID,
                                             JobName = x.Job.JobName,
                                             JobID = x.JobID
                                          })
                                    .Distinct()
                                    .ToList();

【讨论】:

  • +1。请注意,原始查询按每个选定的“列”或属性分组,这与仅执行.Distinct() 相同,而且ToList&lt;MachineMetrics&gt;() 已更改为仅ToList(),因为基础泛型类型(MachineMetrics)已被因此不需要指定编译器(因为这是前面 .Select() 的返回类型。......我想我会添加这个进一步的解释,因为 OP 说它们是 .NET 和 Linq 的新手。
  • 这是我最初的想法,但在原始代码机器的列表计数为 1,但您的代码机器的列表计数>1(上次运行的列表计数为 42)
  • @rally25rs - 似乎不同的方法无法正常工作。机器列表在每个索引处都包含相同的对象。
  • 如果 Distinct 不能正常工作,那么它可能是对象比较的问题。您可以尝试创建一个实现 MachineMetrics 类型的 IEqualityComparer 的新类。这允许您定义什么构成此对象的相等性。您将把这个新类作为参数传递给 Distinct。
【解决方案2】:

Ladislav 的回答很好,但只是为了展示另一种选择,保留 GroupBy,您可以将其简化为:

var machines = prod.Where(p => p.TimeProduced >= start &&
                               p.TimeProduced <= end &&
                               (jobID == -1 ? true : (p.JobID == jobID && p.Job.MachineID == MachineID))).
                    GroupBy(x => new MachineMetrics
                                 {
                                     MachineName = x.Job.Machine.MachineName,
                                     MachineID = x.Job.MachineID,
                                     JobName = x.Job.JobName,
                                     JobID = x.JobID
                                  }).
                    Select(item => item.Key). // 'item' is the grouping, and its 'Key' is the 'MachineMetrics' instance
                    ToList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多