LINQ 中 child 的 child 之和

Sum of child of child in LINQ

我需要有关 EF6 中 LINQ 查询的帮助。

大师table叫EXAM。它的 child 是 ExamResult。 每个 ExamResult 都有一个 Question 和选定的 Answer。 每个 Answerpower (错误为 0,正确为 1)。 如果我想知道正确答案的总数,我只需 运行 命令:

var examTotal = db.Exams.FirstOrDefault(ex => ex.ExamID == examId).ExamResults.Sum(er => er.Answer.Power);

我的问题是有些问题没有得到回答,我得到 NullReferenceException

这应该有效:

var examTotal = db.Exams.FirstOrDefault(ex => ex.ExamID == examId).ExamResults.Count(er => er.Answer.Power == 1);

这不会使用该值,而是查看它是否等于 1,因此不会生成任何 NullReferenceException

试试这个:

var examTotal = db.Exams.FirstOrDefault(ex => ex.ExamID == examId).ExamResults.Where(er => er.Answer != null).Sum(er => er.Answer.Power);

一些常规的 nullchecks 应该可以解决问题

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);

你的"command"有几个问题。

首先,至少有两个个查询:

(1) var exam = db.Exams.FirstOrDefault(ex => ex.ExamID == examId);

(2) var examTotal = exam.ExamResults.Sum(er => er.Answer.Power);

请注意,第二个实际上在 LINQ to Objects 上下文中执行(由于延迟加载,最终包括一些隐藏的数据库调用)。 在这种情况下,有 2 个可能的地方可以提高 NRE

(A) exam.ExamResults 如果 exam 为空
(B) er.Answer.Power如果 er.Answer 为空

您可以按照其他答案中的建议通过包括空检查来修复它们。

但更好的方法是让您的命令在 LINQ to Entities 上下文中执行单个查询,其中导航属性具有不同的含义:

var examTotal = db.Exams.Where(ex => ex.ExamID == examId)
    .SelectMany(ex => ex.ExamResults)
    .Sum(er => (int?)er.Answer.Power) ?? 0;

唯一需要的技巧是将要求和的字段投影为 nullable 类型(我使用 int? 假设 Power 字段是 int 类型,如果不同,请将其更改为您的类型)。这让 EF 始终 return Sum 而不管 er.Answer 是否为空或 ex.ExamResults 是否为空。