首页 > 解决方案 > EF Core 2.2 GroupBy FirstOrDefault 的替代方案

问题描述

在我的项目中,我目前遇到以下 LINQ 查询的问题:

context.WebPages.GroupBy(x => x.Url).Select(x => new { x.Key, x.FirstOrDefault()?.LogoId } ).ToList();

基本上,我试图从我们的 DB 网页中获取它们的 URL 和分配给它们的第一个徽标 ID。但是,我在警告说:The LINQ expressio could not be translated and will be evaluated locally.由于我存储了几百万个网页,我不想加载不必要的数据。而且我绝对不希望在本地评估表达式。

我尝试了几种 LINQ 表达式的优化,例如:

context.WebPages.GroupBY(x => x.Url, x => new {x.LogoId}).Select(x => new { x.Key, x.FirstOrDefault()?.LogoId } ).ToList();
context.WebPages.GroupBy(x => x.Url).Select(x => new { x.Key, x.First().LogoId } ).ToList();
context.WebPages.GroupBy(x => x.Url).Select(x => x.First()).ToList();
context.WebPages.GroupBy(x => x.Url).ToList();

但我总是以同样的警告告终。唯一可以翻译的查询(但对我来说没用)是:

context.WebPages.GroupBy(x => x.Url).Select(x => x.Key).ToList();

是否有任何替代的 LINQ 表达式可以工作(甚至是一组 LINQ 表达式)?还是我需要使用纯 SQL 表达式?

旁注:我们还计划迁移到 .NET Core 3.0,但那是几个月的遥远未来……我不能等到“那时”。

标签: c#linq.net-core

解决方案


如果我们尝试排除连接怎么样?假设LogoId是一个可比较的类型(例如 int):

var ans = from a in context.WebPages
          where !(from b in context.WebPages where a.Url == b.Url && a.LogoId > b.LogoId select b).Any()
          select new {
              a.Url,
              a.LogoId
          };

更新:我用 EF 2.2.6 对此进行了测试,它生成了(可能效率低下)SQL 很好。

更新 2:我还使用 EF 3 进行了测试,并且可以正常工作。我在 EF 3 中较早Distinct/GroupJoin失败的 SQL 翻译。


推荐阅读