Linq 外部联接对象引用未设置为对象 DefaultIfEmpty 的实例

本文关键字:对象 DefaultIfEmpty 实例 设置 外部 对象引用 Linq | 更新日期: 2023-09-27 18:32:16

我正在尝试生成一份需要进行审计的单位清单,如果审计已经进行,则注明审计日期,如果没有审计,则为空。

我的 Get 方法中有以下内容:

public ActionResult AuditReportList(int stnAssureAuditId)
    {
        //get the data for the list
        var people = new List<People.Models.Person>(Peopledb.People);
        var reports = new List<StnAssureAuditReport>(db.StnAssureAuditReports);
        var units = new List<People.Models.Unit>(Peopledb.Units);
        var auditUnits = new List<StnAssureUnit>(db.StnAssureUnits).Where(x => x.StnAssureAuditId == stnAssureAuditId);
        var auditReportList = from u in auditUnits
                              join r in reports on u.UnitId equals r.UnitId into ur
                              from a in ur.DefaultIfEmpty()
                              select new
                              {
                                  CarriedOut = (a == null ? String.Empty : a.CarriedOut.ToLongDateString()),
                                  StnAssureAuditReportId = (a == null ? 0 : a.StnAssureAuditReportId),
                                  UnitId = a.UnitId,
                                  Complete = (a == null ? false : true),
                                  StnCommId = a.StnCommId,
                                  WatchCommId = a.WatchCommId
                              };
        var auditUnitsList = from u in auditReportList
                             join r in units on u.UnitId equals r.UnitId
                             select new 
                             {
                                 UnitId = u.UnitId,
                                 UnitName = r.UnitName,
                                 CarriedOut = u.CarriedOut,
                                 StnAssureAuditReportId = u.StnAssureAuditReportId,
                                 Complete = u.Complete,
                                 StnCommId = u.StnCommId,
                                 WatchCommId = u.WatchCommId
                             };
        var reportStnComm = (from c in auditUnitsList
                             join d in people on c.StnCommId equals d.PersonId
                             select new ReportStnComm
                             {
                                 StnAssureAuditReportId = c.StnAssureAuditReportId,
                                 StnComm = d.FirstName + " " + d.LastName,
                                 WatchCommId = c.WatchCommId,
                                 UnitName = c.UnitName,
                                 CarriedOut = c.CarriedOut,
                                 UnitId = c.UnitId,
                                 Complete = c.Complete,
                             }).ToList();
        var reportList = (from h in reportStnComm
                          join f in people on h.WatchCommId equals f.PersonId
                          select new StnAssureReportList
                          {
                              CarriedOut = h.CarriedOut,
                              StnAssureAuditReportId = h.StnAssureAuditReportId,
                              StnComm = h.StnComm,
                              UnitName = h.UnitName,
                              WatchComm = f.FirstName + " " + f.LastName,
                              UnitId = h.UnitId,
                              Complete = h.Complete,
                          }).OrderBy(x => x.UnitName).ToList();

        var viewModel = reportList.Select(t => new AuditReportListViewModel
        {
            CarriedOut = t.CarriedOut,
            StnAssureAuditReportId = t.StnAssureAuditReportId,
            StnComm = t.StnComm,
            UnitName = t.UnitName,
            WatchComm = t.WatchComm,
            Complete = t.Complete
        });
        return View("AuditReportList", viewModel);
    }

但是当我运行它时,我得到

对象引用未设置为对象的实例。

在审核报告列表变量上。

查看调试,在三次循环后 a 确实显示为空,我认为在这种情况下 DefaultIfEmpty 会启动,以便 a == null 可以在选择中使用,但它似乎不起作用

Linq 外部联接对象引用未设置为对象 DefaultIfEmpty 的实例

在某些情况下防止

空(三元a == null ? ... : ...)而忘记其他情况是一个错误。您应该警惕所有情况。在这里,它不是在UnitIdStnCommIdWatchCommId上完成的。

旁注:在我的团队中,我要求禁止像语法一样使用 linq sql。在我看来,这是一个"错误的好主意"。在 .Net 中编写像编译查询一样编写 sql 很有吸引力,但在实践中我们发现它们的可读性和可理解性远不如基于 linq lambda 的扩展(如 Where(a => ...)Select(a => ...) 等)。

您的问题与行from a in ur.DefaultIfEmpty()有关。如果ur为空,则a的值nullStnAssureAuditReport ,因此当查询尝试计算u.UnitId时,您会得到一个NullReferenceException

仅当IQueryable<StnAssureAuditReport> ur时才可以使用from a in ur.DefaultIfEmpty() select { u.UnitId } - 转换为 SQL 会自动为您处理null情况。但是,当ur IEnumerable<StnAssureAuditReport>时(就像您的情况一样),则会评估u.UnitId并引发空异常。

我专注于u.UnitId属性,但所有u.*调用也是如此。