我最近在尝试使用skip并接受LINQ语句时遇到了错误。
我的陈述看起来像这样。
DbConxtext.MyTable.Get(c => c.UserID == id)
.OrderBy(orderProperty).Skip(index).Take(length).ToList();
这给了我这个错误
'OFFSET'附近的语法不正确。\ r \ n \ nNINCH语句中NEXT选项的使用无效
我发现这是因为OFFSET NEXT和FETCH在sql server 2008上不起作用,但我知道我在我的代码中的其他地方使用分页,它们都运行良好。
有效的和之间的区别在于 Skip 和 Take 是Enumerable的扩展,对那些工作和Queryable的扩展没有。< / p>
因此,在查询中添加 AsEnumerable()可以解决问题。这似乎生成了使用 SELECT TOP(10)而不是 OFFSET 和 FETCH 的SQL。 编辑: 再次阅读本文后,我意识到AsEnumerable不会生成不同的SQL。它将改为执行查询并执行Skip Take in memory。 我的问题是使用Skip和Take作为Enumerable和Queryable的扩展之间有什么区别。 为什么EF决定在两种情况之间生成不同的SQL。DbConxtext.MyTable.Get(c => c.UserID == id)
.OrderBy(orderProperty).AsEnumerable().Skip(index).Take(length).ToList();
答案 0 :(得分:1)
使用
Skip
和Take
作为Enumerable
与Queryable
的扩展名有何区别。
当您在实施Skip
的类型上调用Take
或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,请参阅this question了解备用解决方案。