LINQ - SELECT最小值,仅当集合不为null时

时间:2015-09-19 09:17:52

标签: c# linq mvvm

我有以下(简化)模型:

public class ClockinReport_PerMachine
{
    public ObservableCollection<Clockin_Categories> Categories { get; set; }
}
public class Clockin_Categories
{
    public ObservableCollection<ClockinReport_Day> Report { get; set; }
}
public class ClockinReport_Day
{
    public DateTime Day { get; set; }
}

然后在我的ViewModel中,我有以下内容:

public ObservableCollection<ClockinReport_PerMachine> MachineReport {get;set;}

逻辑如下:

  • 您有多台机器
  • 每台机器都有我们报告的几个类别(例如错误 - 没有纸张,错误 - 没有墨水,......只是一个例子)
  • 在每个类别中,都有日常事件,除了其他事项,我们会在发生问题时跟踪确切的日期时间

我有以下脚本,它返回所有 MachineReports 的最小日期时间

PeriodFrom = MachineReport.Min(n => n.Categories.Min(x => x.Report.Min(z => z.Day)));

这个LINQ遍历所有机器,循环遍历所有类别并查看报告并检查最小DateTime是什么(至少我认为它是什么)。

类别不包含任何元素时,会出现问题。然后它返回一个错误Sequence contains no elements

如何更改我的LINQ,如果没有元素,它会忽略类别?

FINAL:

最后检查collection是否为null对我来说不起作用,因为我的集合包含0个元素(它在启动时初始化)。因此,我不得不稍微编辑我对以下内容的回答:

PeriodFrom = MachineReport.Min(n => n.Categories.Where(b=>b.Report.Count>0).Min(x => x.Report.Max(z => z.Day)));

3 个答案:

答案 0 :(得分:2)

PeriodFrom = MachineReport.Min(n => n.Categories.
                                      Where(c => c != null).
                                      Min(x => x.Report.Min(z => z.Day)));

答案 1 :(得分:2)

由于您选择的是最小值(最小值),您可以使用DefaultIfEmpty()方法,如下所示:

PeriodFrom = MachineReport
    .SelectMany(n =>
        n.Categories.SelectMany(x =>
            x.Report.SelectMany(z =>
                (DateTime?)z.Day
            )
        )
    )
    .DefaultIfEmpty()
    .Min();

请注意,Min()会在序列为空时为您提供null

答案 2 :(得分:1)

您应该测试表达式中的Categories是否为null。 像

这样的东西
PeriodFrom = MachineReport.Min(n => (n.Categories != null &&
n.Categories.Min(x => x.Report.Min(z => z.Day))));