EF Core中GroupBy与Where的LINQ表达式翻译问题
解决方案:避免EF Core 7分组翻译问题,实现服务器端评估
问题根源
你遇到的是EF Core 7的已知限制:当查询返回IGrouping对象时,EF无法将整个表达式完全翻译成SQL,会触发客户端评估;而统计数量的方法能正常工作,是因为最终只返回聚合后的数值,不需要序列化分组对象。
修改获取重复条目列表的方法
不要直接返回分组,而是先筛选出拥有多个条目的OwnerId,再用这些ID关联回原表获取具体条目,全程在服务器端执行:
public async Task<IEnumerable<ItemType>> GetItemsWithDuplicateOwners() { // 第一步:查询所有拥有重复条目的OwnerId(服务器端执行) var duplicateOwnerIds = await GetItemsSecureAsync() .Where(item => item.OwnerId != null) .GroupBy(item => item.OwnerId) .Where(group => group.Count() > 1) .Select(group => group.Key) .ToListAsync(); // 第二步:用筛选出的ID获取对应条目(服务器端执行) return await GetItemsSecureAsync() .Where(item => duplicateOwnerIds.Contains(item.OwnerId)) .ToListAsync(); }
修复扩展方法
原扩展方法的GroupBy+SelectMany写法在EF Core 7中翻译存在问题,改成先取重复Key再过滤的逻辑:
public static async Task<IEnumerable<T>> NonDistinctAsync<T, TKey>(this IQueryable<T> source, Expression<Func<T, TKey>> keySelector) where TKey : notnull { var duplicateKeys = await source .GroupBy(keySelector) .Where(g => g.Count() > 1) .Select(g => g.Key) .ToListAsync(); return source.Where(item => duplicateKeys.Contains(keySelector.Compile()(item))); } // 使用示例: // var duplicateItems = await GetItemsSecureAsync().NonDistinctAsync(item => item.OwnerId);
额外注意点
- 替换
.Result为await:同步调用异步方法(.Result)可能导致死锁,始终使用异步语法保证代码健壮性。 - 若EF Core版本可升级,后续版本已修复类似分组翻译问题,升级到EF Core 8+可简化写法。
内容的提问来源于stack exchange,提问作者Luk164
相关产品推荐
相关产品推荐

