EF Core 6 Where子句要求非空仍查询出Null值问题
问题结论
这是EF Core 6版本的已知Bug,不属于破坏性变更或功能设计限制,是该版本查询优化器的逻辑缺陷导致的。
原因分析
EF Core 6版本新增了子查询合并、重复逻辑简化的性能优化逻辑,该逻辑存在漏洞:当Where条件中对相同筛选、排序规则的子集合调用First()后访问属性做非空判断时,优化器错误地将整个条件简化为仅校验子集合是否存在符合筛选条件的元素,直接忽略了后续的属性非空校验步骤,最终生成的SQL完全缺失SomeOtherNullableDateTime IS NOT NULL的过滤条件,导致查询结果出现不符合预期的Null值。
解决方案
- 短期规避:重写Linq查询的Where条件,避免在
First()后直接做属性判断,改为在子集合筛选条件中直接加入属性非空校验,示例如下:
Parent.Include(p => p.Children) .Where(p => p.Children.Any(c => c.SomeNullableDateTime == null) // 调整此处逻辑,把属性非空校验放到子查询的筛选条件里 && p.Children .Where(c => c.SomeNullableDateTime == null && c.SomeOtherNullableDateTime != null) .OrderBy(c => c.SomeInteger) .Any() ) .Select(p => p.Children .Where(c => c.SomeNullableDateTime == null) .OrderBy(c => c.SomeInteger) .First() .SomeOtherNullableDateTime) .ToList();
也可以优先用查询表达式的let语法存储子查询结果,避免重复写相同逻辑同时降低优化器出错概率:
var result = (from p in Parent.Include(p => p.Children) let firstChild = p.Children.Where(c => c.SomeNullableDateTime == null).OrderBy(c => c.SomeInteger).First() where firstChild != null && firstChild.SomeOtherNullableDateTime != null select firstChild.SomeOtherNullableDateTime).ToList();
- 永久修复:直接升级到EF Core 7及以上版本,该Bug已经在后续版本中被官方修复,升级后原Linq查询即可生成和EF Core 5一致的正确SQL语句。
内容的提问来源于stack exchange,提问作者René
相关产品推荐
相关产品推荐

