【问题标题】:EF Core groupBy no SQL translation for null-coalescing operator (??). ISNULL is not being used to translate when doing ??0mEF Core groupBy 没有空合并运算符 (??) 的 SQL 翻译。做 ??0m 时不使用 ISNULL 进行翻译
【发布时间】:2020-04-26 22:28:18
【问题描述】:

将 EF Core 2.2 与

结合使用
optionsBuilder.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));

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

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

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

【问题讨论】:

  • 由于您没有提到任何编译时错误,因此可以安全地假设 Value 可以为空。话虽如此,您能否提供更多信息,抛出什么异常?或者可能显示由IQueryable 接口准备的sql。我还没有看到实体框架被这么简单的.Select
  • 是的,它可以为空,并且异常由 QueryClientEvaluationWarning 触发。这是因为没有 ??0m 它被转换为 SQL 并在服务器端正确评估,但 ??0m 它没有被翻译然后在客户端评估,在我的情况下,由于启用警告而触发异常。关于这个主题有很多讨论,因为客户端评估是 ef core 2.2 上的默认行为,并且在 ef core 3.x 上已被删除
  • 您能否显示至少部分表架构、t 在此上下文中的类模型以及 linq 语句的其余部分?
  • 表模式可以是id,value。 (整数,整数)。和查询 db.MyTable.GroupBy(t => t.id).Select(g=> new { Id = g.Key, Total = g.Sum(t=>t.Value??0m)}).ToArray ();
  • 嗯 0m 基本上就是你说的(decimal)0。如果Value 是typeOf(int),你的.Select 应该不是.Select(t => t.Value ?? 0)

标签: c# sql-server entity-framework-core ef-core-2.2


【解决方案1】:

这是 EF Core 2.2 GroupBy 查询翻译器缺陷/限制(已在 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) // <--
    });

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

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

【讨论】:

  • 好的,谢谢,但是在 sql 翻译方面发生了什么?为什么是 g.Sum(e => e.SomeValue) ? 0m 工作而不是 g.Sum(e => e.SomeValue ?? 0m) ?你是说一旦升级到 ef core 3 这个问题就会消失?
  • 是的,它消失了。正如我在开始时所说,这是 2.x 缺陷,可以使用查询的第二个变体中显示的临时投影技巧来修复。第三种变体有效,因为?? 不在Sum 方法内(这是前面提到的2.2 限制/缺陷)。
猜你喜欢
  • 2020-11-12
  • 2021-03-29
  • 2021-05-25
  • 2018-03-08
  • 2014-07-14
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多