LINQ 中子项的子项的总和
本文关键字:LINQ | 更新日期: 2023-09-27 18:36:31
我需要 EF6 中 LINQ 查询的帮助。
主表称为 EXAM
。它的子表是 ExamResult
。每个ExamResult
都有一个Question
和选定的Answer
。每个Answer
都有power
(如果错误,则为 0,如果正确,则为 1)。如果我想知道正确答案的总数,我只需运行以下命令:
var examTotal = db.Exams.FirstOrDefault(ex => ex.ExamID == examId).ExamResults.Sum(er => er.Answer.Power);
我的问题是当一些问题没有得到回答时,我得到了NullReferenceException
.
你的"命令"有几个问题。
首先,至少有两个查询:
(1) var exam = db.Exams.FirstOrDefault(ex => ex.ExamID == examId);
(2) var examTotal = exam.ExamResults.Sum(er => er.Answer.Power);
请注意,第二个实际上是在 LINQ to Objects 上下文中执行的(最终包括由于延迟加载而隐藏的一些数据库调用)。在这种情况下,有两个可能的地方可以提高 NRE
(A) exam.ExamResults
如果exam
为空
(B) er.Answer.Power
如果er.Answer
为空
您可以通过包含其他答案中建议的空检查来修复它们。
但更好的方法是让您的命令在 LINQ to 实体上下文中执行单个查询,其中导航属性具有不同的含义:
var examTotal = db.Exams.Where(ex => ex.ExamID == examId)
.SelectMany(ex => ex.ExamResults)
.Sum(er => (int?)er.Answer.Power) ?? 0;
唯一需要的技巧是将要求和的字段投影为可为空的类型(我使用过int?
假设Power
字段是int
类型,如果不同,请将其更改为您的类型)。这允许 EF 始终返回Sum
,无论er.Answer
为 null 还是ex.ExamResults
为空。
一些一般的空检查应该可以解决问题
var exam = db.Exams.FirstOrDefault(ex => ex.ExamID == examId);
var examTotal = exam.ExamResults.Sum(er => er.Answer?.Power ?? 0);
。以防万一你没有使用 C# 6,下面是它的另一个版本:
var exam = db.Exams.FirstOrDefault(ex => ex.ExamID == examId);
var examTotal = exam.ExamResults.Sum(er => er.Answer != null ? er.Answer.Power : 0);
试试这个:
var examTotal = db.Exams.FirstOrDefault(ex => ex.ExamID == examId).ExamResults.Where(er => er.Answer != null).Sum(er => er.Answer.Power);
这应该有效:
var examTotal = db.Exams.FirstOrDefault(ex => ex.ExamID == examId).ExamResults.Count(er => er.Answer.Power == 1);
这将不使用该值,而是查看它是否等于 1,因此不会生成任何NullReferenceException
。