You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core3.1+EF5.0.9下无需AsEnumerable的可翻译GroupBy查询方案问询

问题根因

EF Core 3.0及以上版本默认关闭了隐式客户端评估,你原有写法中GroupBy后取First()的操作无法直接翻译成SQL(SQL标准中的GROUP BY仅支持聚合操作,不支持直接取分组内首条记录),才会触发报错。

替代写法(无需加AsEnumerable)

场景1:仅需统计分组数量(匹配你当前示例的最终Count()需求)

你给出的示例代码本质是统计符合条件的记录中,不同SM_PROVIDER_ID的去重计数,完全可以简化为以下写法,全程可被EF 5翻译为SQL执行:

var count = unitOfWork.GetRepository<MAPPING_TABLE>()
    .GetAll(predicate: x => x.USER_ID == userId)
    .Select(x => x.Site.SM_PROVIDER_ID)
    .Distinct()
    .Count();

这种写法不需要加载任何关联导航属性,执行效率远高于原有全量加载实体到内存分组的方案。

场景2:需要获取每个分组首条的完整实体数据

如果你需要返回每个SM_PROVIDER_ID对应的首条完整记录(包含你示例中Include的所有导航属性),可以借助EF 5支持翻译的RowNumber窗口函数实现:

// 获取每个分组首条实体的查询
var entityQuery = unitOfWork.GetRepository<MAPPING_TABLE>()
    .GetAll(predicate: x => x.USER_ID == userId)
    .Include(p => p.Site).ThenInclude(p => p.Provier).ThenInclude(p => p.Location)
    .AsNoTracking()
    .Select(x => new 
    {
        Entity = x,
        // 按SM_PROVIDER_ID分区,可自定义排序规则决定哪条是首条
        RowNum = EF.Functions.RowNumber<int>(
            partitionBy: x.Site.SM_PROVIDER_ID, 
            ordering: x => x.Id)
    })
    .Where(x => x.RowNum == 1)
    .Select(x => x.Entity);

// 计数直接调用Count()
var count = entityQuery.Count();
// 取实体列表调用ToList()
var entityList = entityQuery.ToList();

注意事项

  • 上述两种写法均全程在数据库侧执行,不需要客户端内存分组,数据量较大时性能优势会非常明显。
  • 窗口函数写法中的排序规则可根据你的实际业务需求调整,比如按创建时间倒序取最新的一条记录。

内容的提问来源于stack exchange,提问作者Paritosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 21:12:02