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

EFCore SQLite中Linq的Take().Last()查询结果不符预期如何解决?

解决EF Core SQLite中Take().Last()返回错误结果的问题

这个问题我之前在EF Core SQLite开发时也踩过坑,本质是EF Core对Last()方法的SQL转换逻辑在这种场景下出了问题,咱们一步步来拆解解决:

问题根源

SQLite本身没有原生的LAST()函数,EF Core处理Last()时,默认会把它转成ORDER BY [列名] DESC LIMIT 1的SQL语句。但当你在Take(20)之后调用Last()时,EF Core的查询翻译器并没有正确组合这两个操作——它直接忽略了前面的Take(20)限制,对整个数据集执行了反向排序取第一条的操作,这就导致你拿到的是全表最后一条,而非前20行的最后一条。

修复方案

有两种简单高效的替代写法,都能让EF Core生成正确的SQL:

方法一:反向排序后取第一条

既然Last()的本质是取排序序列的最后一项,那我们可以对Take(20)后的结果反向排序,再取第一条,就能得到前20行的最后一条数据:

// 原错误代码
// long tEnd = current.Last().Time;

// 修改后代码
long tEnd = current.OrderByDescending(row => row.Id).First().Time;

EF Core会生成这样的SQL,确保先取前20行,再从中获取最后一条:

SELECT TOP(1) [t].[Time]
FROM (
    SELECT TOP(20) [d].[Id], [d].[Time]
    FROM [DataEntry] AS [d]
    ORDER BY [d].[Id]
) AS [t]
ORDER BY [t].[Id] DESC

方法二:跳过前19条取第一条

因为你已经通过OrderBy(row => row.Id).Take(20)拿到了按Id升序的前20行,那前20行的最后一条就是第20条,直接跳过前19条取第一条即可:

long tEnd = current.Skip(19).First().Time;

这种写法生成的SQL更简洁高效:

SELECT [d].[Time]
FROM [DataEntry] AS [d]
ORDER BY [d].[Id]
LIMIT 1 OFFSET 19

额外提示

尽量避免在EF Core查询中直接使用Last()/LastOrDefault(),尤其是搭配Take()/Skip()这类限制条件时——不同数据库的查询翻译器对这类组合的支持差异较大,用OrderByDescending().First()或Skip(n).First()的写法兼容性更强,逻辑也更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:46:15