使用DefaultIfEmpty进行左外部联接会引发NullReferenceException

时间:2019-07-15 11:39:25

标签: c# linq

我有3个列表(报告,userPrinters,allPrinters),我使用LINQ将它们连接在一起。 reports包含报告列表,userPrinters包含每个报告的用户首选的打印机名称和纸张来源(报告列表可能为空或不是一对一),并且allPrinters是系统上的打印机列表(可能与用户的打印机没有相同的打印机)。

所以我的查询是:

var list = (from r in reports
    join u in userPrinters on r.Id equals u.ReportId into up
    from userPrinter in up.DefaultIfEmpty()
    join p in allPrinters on userPrinter.PrinterName equals p.Name into ps
    from printer in ps.DefaultIfEmpty()
    select new PrinterSelection() {
        Report = r,
        Printer = printer,                 
        Source = (from s in printer.Sources
           where s.Type == userPrinter.PaperSource
           select s).FirstOrDefault()
       }).ToList();

因此,通过上面的查询,我得到了所有报告,左外连接用户的打印机,然后左外连接所有打印机。

但是,当我包含第二个左外部联接时,我得到一个NullReferenceException

DefaultIfEmpty应该返回默认的单例吗?我想念什么?

2 个答案:

答案 0 :(得分:1)

感谢@lakobski的评论。我错过了默认值的构造函数。因此,这是有效的更新后的LINQ:

var list = (from r in reports
    join u in userPrinters on r.Id equals u.ReportId into up
    from userPrinter in up.DefaultIfEmpty(new UserPrinter())
    join p in allPrinters on userPrinter.PrinterName equals p.Name into ps
    from printer in ps.DefaultIfEmpty(new Printer())
    select new PrinterSelection() {
        Report = r,
        Printer = printer,                 
        Source = (from s in printer.Sources
           where s.Type == userPrinter.PaperSource
           select s).FirstOrDefault()
       }).ToList();

答案 1 :(得分:0)

您必须对userprinter变量进行null检查,如下所示,

join p in allPrinters on (userPrinter== null ? "no-value" : userPrinter.PrinterName) equals 
p.Name