EF无法翻译LINQ查询:如何改写为可被翻译的查询?
解决方案
EF无法翻译带索引参数的Select((x, i) => ...),因为该索引是内存枚举时的序列位置,数据库本身没有对应的原生语法支持。以下是两种可行的改写方式:
方式一:客户端评估(适合数据量较小的场景)
将排序后的结果切换到客户端处理,再添加索引:
await _dbContext.VwJobSupplierWithScores .Where(x => x.JobId == jobId && x.SupplierKey == supplierKey) .OrderBy(x => x.SpendCurrencyJob) .AsAsyncEnumerable() // 切换为客户端异步枚举,后续操作在本地执行 .Select((x, i) => new { item = x, index = i }) .FirstOrDefaultAsync()!;
说明:Where和OrderBy仍在数据库端执行,仅Select带索引的逻辑在本地内存中处理,避免大量数据传输的前提是Where过滤后结果集较小。
方式二:数据库端生成行号(适合数据量较大的场景)
利用EF的窗口函数RowNumber()在数据库端生成行号,再转换为0起始的索引:
await _dbContext.VwJobSupplierWithScores .Where(x => x.JobId == jobId && x.SupplierKey == supplierKey) .Select(x => new { item = x, // RowNumber()返回1起始的行号,减1转为0起始的索引 index = EF.Functions.RowNumber().Over(orderBy: o => o.OrderBy(x => x.SpendCurrencyJob)) - 1 }) .FirstOrDefaultAsync()!;
说明:整个查询逻辑都在数据库端执行,适合需要处理大数据量的场景,避免将过多数据拉取到客户端。
另外注意:原代码中FirstOrDefaultAsync()后多了一个冗余括号,已在改写代码中修正。
内容的提问来源于stack exchange,提问作者Eugene Sukh
相关产品推荐
相关产品推荐

