我最近在尝试使用skip并接受LINQ语句时遇到了错误。
我的陈述看起来像这样。
DbConxtext.MyTable.Get(c => c.UserID == id)
.OrderBy(orderProperty).Skip(index).Take(length).ToList();
这给了我这个错误
'OFFSET'附近的语法不正确。\ r \ nn FETCH语句中NEXT选项的使用无效
我发现这是因为OFFSET NEXT和FETCH在sql server 2008上不起作用,但我知道我在我的代码中的其他地方使用分页,它们都运行良好。
有效的和那个之间的区别在于Skip和Take是Enumerable的扩展,对那些有效的和可查询的那些没有。
所以在查询中添加AsEnumerable()为我解决了问题。这似乎生成了使用SELECT TOP(10)而不是OFFSET和FETCH的 SQL。
编辑: 再次阅读此内容后,我意识到AsEnumerable不会生成不同的SQL。它将改为执行查询并执行Skip Take in memory。
DbConxtext.MyTable.Get(c => c.UserID == id)
.OrderBy(orderProperty).AsEnumerable().Skip(index).Take(length).ToList();
我的问题是使用Skip和Take作为Enumerable和Queryable的扩展之间的区别是什么。
为什么EF决定在两种情况之间生成不同的SQL。
使用
Skip
和Take
作为Enumerable
和Queryable
扩展之间的区别是什么。
当您调用Skip
或Take
on实现IQueryable
的类型时,将绑定Queryable
扩展方法,并且底层的Linq提供程序(例如Linq-to-Entities)将处理Skip
和/或Take
并将其转换为底层的命令数据提供者(例如SQL语句)。提供者是否实际支持它们或正确处理它们直到运行时才会知道。
当您在实现IEnumerable
(但不是IQueryable
)的类型上调用它们时,将绑定Enumerable
扩展方法, Queryable
查询生成的内存中集合上的命令。
为什么EF决定在两种情况之间生成不同的SQL。
在第二种情况下,生成的SQL查询仅包含命令,直到您注入AsEnumerable()
。这就是EF提供商所看到的一切。从那时起,命令将绑定到Enumerable
扩展方法,并将处理内存中的其余命令。
这似乎生成使用SELECT TOP(10)的SQL
我非常怀疑。 应该发生的是SQL查询将返回所有记录,但Take
生成的内存中迭代器将只返回前十个。
如果要为SQL 2008数据库正确处理SKIP和TAKE,请参阅此问题以获取备用解决方案。