在 EF LINQ 查询 if 子句中引发空引用异常
Posted
技术标签:
【中文标题】在 EF LINQ 查询 if 子句中引发空引用异常【英文标题】:Null reference exception being thrown in EF LINQ query if-clause 【发布时间】:2018-06-17 20:07:21 【问题描述】:我找不到确切的词来解释发生了什么,所以如果这是一个重复的问题,我很抱歉。
我尝试在 LINQ 查询中执行一个非常简单的 AND 条件 if 子句,以检查对象是否为空,然后验证其属性是否等于我想要比较的列。
代码:
public IEnumerable<Plan> GetPlans(Plan plan)
return _context.Plans.Where(e =>
e.Situation == plan.Situation &&
e.Notes.Contains(plan.Notes) &&
(plan.Excercise != null && plan.Exercise.Year > 0 ? e.Exercise.Year == plan.Exercise.Year: true)).ToList();
我之前已经在 .NET 4.5 中进行过十几次此类检查,没有出现任何问题。
但是现在,在我正在处理的第一个 .NET Core 2.0 项目中,我遇到了以下错误:
An exception was thrown while attempting to evaluate a LINQ query parameter expression. To show additional information call EnableSensitiveDataLogging() when overriding DbContext.OnConfiguring.
内部异常更清楚:NULL REFERENCE EXCEPTION。
经过一些测试,我发现错误发生在 plan.Exercise 为空时,即使我尝试通过首先检查它是否为空来避免异常。
如果我尝试直接在即时窗口中进行相同的检查,它会返回“false”,应该是这样。
我在这里遗漏了什么吗?这可能是一个EF错误?例如,为什么这在 .NET 4.5 中有效,而在 .NET Core 2.0 中无效?
提前致谢。
更新
Ivan 的解决方案成功了:
重写? : 等价的构造||
plan.Excercise == null || plan.Exercise.Year <= 0 || e.Excercise.Year == plan.Exercise.Year
【问题讨论】:
查看null condition operator 让我们澄清一下条款。您是在询问 EF Core 2.0 吗?如果是,NET 4.5 和 NET Core 应该是无关的(EF Core 2.0 不支持 NET 4.5)。请相应地更新帖子和标签。 @thiagoprzy 你没抓住重点。 EF Core 及其版本是最重要的知识,而不是 NET (Core)。无论如何,这是 EF Core 错误(现在无法在他们的问题跟踪器中找到它)。用等效的||
重写 ? :
结构,例如plan.Excercise == null || plan.Exercise.Year <= 0 || e.Excercise.Year == plan.Exercise.Year
@IvanStoev 好的,我明白了。当问题应该代表 EF 时,我正在谈论 .NET。对于那个很抱歉。您的解决方案完成了这项工作。
@Gert 他们正在尝试预评估和消除 const 参数表达式(对 EF6 的改进,我试图使用表达式后处理器 here 进行改进)。他们确实为二进制表达式正确短路,但未能为条件运算符这样做。
【参考方案1】:
听起来这可能是 EF Core 中的一个错误(但我不确定)。
如果不满足plan
的基本要求,您可能会尝试的一件事是快速失败,更重要的是,不要使用三元运算符,而是使用传统的比较运算符和括号:
public IEnumerable<Plan> GetPlans(Plan plan)
if (plan == null) return new List<Plan>();
return _context.Plans
.Where(e =>
e.Situation == plan.Situation &&
e.Notes.Contains(plan.Notes) &&
(plan.Exercise == null ||
plan.Exercise.Year <= 0 ||
e.Excercise.Year == plan.Exercise.Year))
.ToList();
【讨论】:
【参考方案2】:为避免此问题,请确保您不是在评估空对象。
var exercice = await _repositoryExercice.FirstOrDefaultAsync(i => i.IsCurrent);
var depenses = _repositoryDepense.GetAll()
.Where( e => e.ExerciceId.Equals(exercice.Id))
.WhereIf(AbpSession.TenantId.HasValue, m => m.TenantId.Value.Equals(AbpSession.TenantId.Value))
.ToList();
问题是由这一行 .Where( e => e.ExerciceId.Equals(exercice.Id))
引起的,因为变量 exercice
为空。
最佳实践,我用这个替换了那行:
...
.WhereIf(exercice != null, e => e.ExerciceId.Equals(exercice.Id))
...
【讨论】:
【参考方案3】:如何将你的代码简化成类似的东西
public IEnumerable<Plan> GetPlans(int year)
return _context.Plans
.Where(e => e.Excercise.Year == year)
.ToList();
【讨论】:
Where 子句中有更多条件,我只是将它们删除以不让代码“混乱”。我将编辑问题以使其更明显。以上是关于在 EF LINQ 查询 if 子句中引发空引用异常的主要内容,如果未能解决你的问题,请参考以下文章