首页 > 解决方案 > EF Core groupBy 没有空合并运算符 (??) 的 SQL 翻译。做 ??0m 时不使用 ISNULL 进行翻译

问题描述

将 EF Core 2.2 与

optionsBuilder.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));

对 sql server 数据库的工作 groupBy linq 查询无法通过将 更改为在服务器端进行Select(t=>t.Value)评估Select(t=>t.Value??0m)

为什么它没有被翻译成 SQL,因为它可能变成 SUM(ISNULL(Value,0)) ?

我知道这没有必要,但我想了解它是如何在幕后工作的,因为我觉得我错过了一些东西。

标签: c#sql-serverentity-framework-coreef-core-2.2

解决方案


这是 EF Core 2.2GroupBy查询翻译器缺陷/限制(已在 EF Core 3.x 中修复),它不支持除了简单的“属性”访问之外的聚合方法表达式。

GroupBy解决方法是使用带有元素选择器的重载,使用包含所有必需表达式(因此它们成为“属性”)的中间(匿名类型)投影。

例如,给定这样的实体:

public class SomeEntity
{
    public int Id { get; set; }
    public int SomeKey { get; set; }
    public decimal? SomeValue { get; set; }
}

和期望的,但像这样的 EFC2.2 查询失败:

var query = db.Set<SomeEntity>()
    .GroupBy(e => e.SomeKey)
    .Select(g => new
    {
        g.Key,
        Value = g.Sum(e => e.SomeValue ?? 0m) // <--
    });

修改后的 EFC2.2 解决方案可能是这样的:

var query = db.Set<SomeEntity>()
    .GroupBy(e => e.SomeKey, e => new { SomeValue = e.SomeValue ?? 0m }) // <--
    .Select(g => new
    {
        g.Key,
        Value = g.Sum(e => e.SomeValue) // <--
    });

更通用的解决方案是将 null 合并运算符移出聚合函数:

var query = db.Set<SomeEntity>()
    .GroupBy(e => e.SomeKey)
    .Select(g => new
    {
        g.Key,
        Value = g.Sum(e => e.SomeValue) ?? 0m // <--
    });

推荐阅读