【问题标题】:What is the server evaluation issue causing this EF Core 3.1 query to fail?导致此 EF Core 3.1 查询失败的服务器评估问题是什么?
【发布时间】:2020-01-23 17:45:31
【问题描述】:

我已经学会了在 EF Core 3.0 中,客户端评估 can only happen on the top level projection(即最后一次调用 Select)。我以为我理解了这个问题,但是在 3.1 下一个查询的失败告诉我我不知道。

这是查询

using (var ctx = new GsContext())
{
    var recs = ctx.Calibrations
                  .Where(ca => ca.DeviceId == deviceId)
                  .AsNoTracking()
                  .Include(c => c.Cartridge)
                  .OrderByDescending(i => i.CalibratedOn)
                  .GroupBy(r => r.CartridgeId)
                  .Select(q => q.First())
                  .ToList();

我没有看到自己在做任何复杂的预测或任何需要在 Select 之前进行客户端评估的事情,所以异常消息让我感到困惑。这是错误消息的文本:

LINQ 表达式'(GroupByShaperExpression: KeySelector: (c.CartridgeId), ElementSelector:(EntityShaperExpression: 实体类型:校准 值缓冲区表达式: (ProjectionBindingExpression:EmptyProjectionMember) IsNullable: 假 ) ) .First()' 无法翻译。要么以可翻译的形式重写查询,要么显式切换到客户端评估 通过插入对 AsEnumerable()、AsAsyncEnumerable() 的调用, ToList() 或 ToListAsync()。看 https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

之前,当我的查询试图在查询的早期进行一些复杂的字符串处理时,我已经遇到过这样的异常(就像我说的,我很难了解这个问题),但这里的情况并非如此,至少我看不到。

我找到了this related question,但在这种情况下,这个人正在 GroupBy 子句中进行投影。我不这样做。

如果有帮助,这里是校准类

public class Calibration
{
    [Key]
    [Required]
    public int      Id                 { get; set; }

    [Required]
    public int      DeviceId           { get; set; }

    [Required]
    public int      CartridgeId        { get; set; }

    [ForeignKey(nameof(CartridgeId))]
    public Cartridge Cartridge          { get; set; }

    public DateTime CalibratedOn     { get; set; }
}

我确信我可以解决这个问题。我要求更好地理解客户端/服务器评估。有人可以向我解释我错过了什么吗?我的查询需要客户评估吗

【问题讨论】:

  • 我很好奇这是否与在分组之前排序有关(分组必须保留 linq-to-object 的顺序,但其他实现,例如 EF,可能不需要这样做所以)。我会试试这个:ctx.Calibrations.Where(ca => ca.DeviceId == deviceId).AsNoTracking().Include(c => c.Cartridge).GroupBy(r => r.CartridgeId).Select(q => q.OrderByDescending(i => i.CalibratedOn).First()).ToList();
  • 感谢尝试,但不幸的是没有帮助。它确实改变了异常中的错误消息。现在它说 OrderByDescending(i => i.CalibratedOn) 无法翻译

标签: entity-framework-core entity-framework-core-3.1


【解决方案1】:

我找到了this related question,但在这种情况下,这个人正在 GroupBy 子句中进行投影。我不这样做。

嗯,这就是问题所在,在我写的链接帖子的my answer 中:

不幸的是,目前 EF Core 3.0 / 3.1 仅支持 GroupBy 服务器翻译带有键/聚合的投影(类似于 SQL)。

换句话说,您必须GroupBy 之后有只包含键和/或聚合的投影,否则它不会翻译。

Here 是相关的 GitHub 问题。以及Complex Query Operators - GroupBy下官方文档的一些解释:

LINQ GroupBy 运算符创建IGrouping<TKey, TElement> 类型的结果,其中TKeyTElement 可以是任意类型。此外,IGrouping 实现了IEnumerable<TElement>,这意味着您可以在分组后使用任何 LINQ 运算符对其进行组合。由于没有数据库结构可以表示IGrouping,因此 GroupBy 运算符在大多数情况下没有翻译。当聚合运算符应用于每个组时,返回一个标量,它可以在关系数据库中转换为 SQL GROUP BY。 SQL GROUP BY 也有限制。它要求您仅按标量值进行分组。投影只能包含分组键列或应用于列的任何聚合。

【讨论】:

  • 该死的。我的问题的所有仔细构造都因未能正确阅读“仅支持”一词而遭到破坏。 (或者显然是通过在心理上将其翻译成“不支持”)。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 2020-05-16
  • 2020-05-18
  • 2010-12-19
相关资源
最近更新 更多