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 可以在选择中使用,但它似乎不起作用
空(三元a == null ? ... : ...
)而忘记其他情况是一个错误。您应该警惕所有情况。在这里,它不是在UnitId
、StnCommId
和WatchCommId
上完成的。
旁注:在我的团队中,我要求禁止像语法一样使用 linq sql。在我看来,这是一个"错误的好主意"。在 .Net 中编写像编译查询一样编写 sql 很有吸引力,但在实践中我们发现它们的可读性和可理解性远不如基于 linq lambda 的扩展(如 Where(a => ...)
、Select(a => ...)
等)。
您的问题与行from a in ur.DefaultIfEmpty()
有关。如果ur
为空,则a
的值null
为 StnAssureAuditReport
,因此当查询尝试计算u.UnitId
时,您会得到一个NullReferenceException
。
仅当IQueryable<StnAssureAuditReport>
ur
时才可以使用from a in ur.DefaultIfEmpty() select { u.UnitId }
- 转换为 SQL 会自动为您处理null
情况。但是,当ur
IEnumerable<StnAssureAuditReport>
时(就像您的情况一样),则会评估u.UnitId
并引发空异常。
我专注于u.UnitId
属性,但所有u.*
调用也是如此。