c# - 强制 SUM 方法在适用于 EF Core 时返回 NULL
问题描述
我正在执行一个查询,我偶尔会期望 NULL 像这样:
.Where(d => d.Id == varid && d.Date >= vardate1 && d.Date <= vardate2)
.Sum(d => (decimal?)d.Delta);
Delta 是不可为空的小数,智能感知显示 Sum 的结果将是小数?因为我介绍了演员。生成的 SQL 符合预期,当手动运行时,如果没有匹配的记录,它会正确返回 NULL。但是,具体化查询的结果始终为 0。此行为与非核心 EF 不同,后者将返回 null。这真的是新的预期行为吗?如果是这样,我如何在需要时强制它返回 null ?Null 和 0 在此上下文中具有不同的含义。
我可以先引入记录,然后在服务器上求和,但如果 EF 核心能够自行完成我所期望的,那就太好了。
解决方案
很可能是一个错误,但知道 EF Core 设计人员对不可空Max
//和Min
/翻译的愿景,如果他们故意这样做是为了模拟(奇怪的)LINQ to Objects 可空行为,它通过结果返回事件,我不会感到惊讶方法的类型可以为空。 Average
First
Single
Sum
0
从下面的代码片段可以看出
decimal? result = Enumerable.Empty<decimal?>().Sum(); // result is 0
甚至记录在案(!?):
评论
source
如果不包含任何元素,此方法返回零。
“有趣”的事情是这仅用于根查询Sum
执行 - 在投影内部它具有您正在寻找的 SQL 行为。
这导致我们通过使用group by 常量技巧结合投影来解决问题。为了不在您需要的任何地方重复它,并且如果它在以后的 EF Core 版本中得到修复,也可以轻松删除它,您可以将它封装在自定义扩展方法中,如下所示:
public static partial class EfCoreExtensions
{
public static decimal? SumOrDefault<T>(this IQueryable<T> source, Expression<Func<T, decimal?>> selector)
=> source.GroupBy(e => 0, selector).Select(g => g.Sum()).AsEnumerable().FirstOrDefault();
}
并更换
.Sum(d => (decimal?)d.Delta);
和
.SumOrDefault(d => d.Delta);
只要确保您仅将它用于最终调用,因为如果您在查询表达式树中使用它,作为任何自定义方法,它将不会被识别并且会导致客户端评估或运行时异常。
推荐阅读
- bash - 为什么通过 Crontab 启动的脚本表现不同?
- django - 无法解码 pdf (xhtml2pdf) 中的俄语符号
- laravel - 为什么创建进程时会丢失最后一个 ID?
- javascript - TypeError:无法读取 .remove() 上未定义的属性“parentElement”
- angular - 如何使用角材料设计箭头网格
- python - 将 PIL 图像转换为字节,出现错误
- jquery - 在 IE9 中使用 jQuery 定位 `source` 元素
- log4j2 - 使用 Async Loggers 时 Log4j2 产生多少线程
- latex - Beamer:图形内的覆盖区域?
- xslt - 如何自定义地理网络中的“导出为 csv”功能?