Skip()和Take()为可枚举与可查询

时间:2017-08-25 17:51:14

标签: c# entity-framework linq-to-sql entity-framework-6

我最近在尝试使用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。

DbConxtext.MyTable.Get(c => c.UserID == id)
    .OrderBy(orderProperty).AsEnumerable().Skip(index).Take(length).ToList();

我的问题是使用Skip和Take作为Enumerable和Queryable的扩展之间有什么区别。

为什么EF决定在两种情况之间生成不同的SQL。

1 个答案:

答案 0 :(得分:1)

  

使用SkipTake作为EnumerableQueryable的扩展名有何区别。

当您在实施Skip的类型上调用TakeIQueryable时,将绑定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了解备用解决方案。