EF Core 8报错“EmptyProjectionMember不在字典中”求解决方案
解决EF Core分组取用户最高得分Attempt的查询错误
你的查询报错是因为EF Core无法将GroupBy后直接在分组内排序取首项的逻辑正确翻译成SQL,触发了客户端评估时的内部错误,同时这种写法还可能导致大量数据加载到服务器内存。以下是纯数据库端执行的解决方案:
使用EF Core支持的**窗口函数ROW_NUMBER()**来实现分组取最大值的逻辑,整个查询会被完整翻译成SQL在数据库端执行,不会加载多余数据:
IQueryable<Attempt> GetBestAttempts() => db.Attempt // 为每个Attempt生成分组内的行号:按UserId分组,组内按score降序编号 .Select(a => new { Attempt = a, RowNumber = EF.Functions.RowNumber() .Over(PartitionBy(a.UserId) .OrderByDescending(a => a.score)) }) // 筛选每组的第一行(即最高分的Attempt) .Where(x => x.RowNumber == 1) // 提取对应的Attempt实体 .Select(x => x.Attempt) // 最终按得分、UserId排序 .OrderByDescending(a => a.score) .ThenBy(a => a.UserId);
补充说明
- 如果同一个用户有多个得分相同的最高分Attempt,上述写法会只保留其中一个(具体保留哪一个由数据库内部排序规则决定,比如Id顺序)。如果需要保留所有同分的记录,将
RowNumber()替换为Rank()即可。 - 该方案完全避免了客户端评估,所有逻辑在数据库端完成,符合你“无需实例化查询、避免大量数据加载”的需求。
内容的提问来源于stack exchange,提问作者Tomer Trashman
相关产品推荐
相关产品推荐

