详解LINQ to SQL分页问题 不同版本对比

开发 后端
本文将为大家介绍在.NET 3.5和.NET 4下LINQ to SQL分页问题的异同,希望对大家了解LINQ有所帮助。

[[12004]]

从 .NET Framework 有了 LINQ,SQL 分页有了新的选择,那就是简单使用 Skip 及 Take 方法。当然,别忘了加上排序。本以为对此没有什么可怀疑的,殊不知在我们的产品 SE 中却碰到了很奇怪的一个问题:对某张表的执行分页查询,有一条数据在所有分页中均没有出现。通过查看真正执行的 SQL 发现,SqlProvider 翻译的第一页的 SQL 用的是 TOP N,而其他分页用的是 ROW_NUMBER 函数 + 范围限定。多的不说,仅从二者的不同,我就觉得其结果不能划等号。但是,在另建的测试中,我发现二者结果没有什么问题。百思不得其解之余,也只能自我安慰说 MS 会保证二者逻辑一致,至于为何用不同的方法,那是出自性能的考虑。

直至今日,突然想起这个问题,就 GOOGLE 了一把,看看是否有同学碰到这样的问题。结果就找到了: 利用 LINQ to SQL 對資料做分頁時應注意的事 ( 重要 ),其结论就是要注意使用 OrderBy 方法,否则数据逻辑不对。然后按其说的进行了测试,实际情况确实如此,但是我也加了排序,为何还有问题呢?我暂时没办法重现这个问题,因为业务数据在变化,现在看来又正常了。

解铃还需系铃人,只能期望 MS 在新的版本中解决这个问题了。办法很简单:首页不用 TOP N,而是统一使用 ROW_NUMBER 函数。由于 SE 还服务器端的代码没有使用 .NET Framework 4 编译,所以也就一直没有尝试。今天测试了一下,发现在 NF 4.0 中,已经修正了这个问题,结果如下:

  1. SELECT [t1].[ID], [t1].[Name], [t1].[CreateTime]  
  2. FROM (  
  3.     SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID], [t0].[Name], [t0].[CreateTime]  
  4. AS [ROW_NUMBER], [t0].[ID], [t0].[Name], [t0].[CreateTime]  
  5.     FROM [dbo].[TableA] AS [t0]  
  6.     ) AS [t1]  
  7. WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1  
  8. ORDER BY [t1].[ROW_NUMBER]  
  9. -- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [0]  
  10. -- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [5]  
  11. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1  
  12.  
  13. SELECT [t1].[ID], [t1].[Name], [t1].[CreateTime]  
  14. FROM (  
  15.     SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID], [t0].[Name], [t0].[CreateTime]  
  16. AS [ROW_NUMBER], [t0].[ID], [t0].[Name], [t0].[CreateTime]  
  17.     FROM [dbo].[TableA] AS [t0]  
  18.     ) AS [t1]  
  19. WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1  
  20. ORDER BY [t1].[ROW_NUMBER]  
  21. -- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [5]  
  22. -- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [5]  
  23. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1 

比对一下:

  1. SELECT TOP (5) [t0].[Name], [t0].[ID], [t0].[CreateTime]  
  2. FROM [dbo].[TableB] AS [t0]  
  3. ORDER BY [t0].[ID]  
  4. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926  
  5.  
  6. SELECT [t1].[Name], [t1].[ID], [t1].[CreateTime]  
  7. FROM (  
  8.     SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID]) AS [ROW_NUMBER], [t0].[Name],  
  9. [t0].[ID], [t0].[CreateTime]  
  10.     FROM [dbo].[TableB] AS [t0]  
  11.     ) AS [t1]  
  12. WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1  
  13. ORDER BY [t1].[ROW_NUMBER]  
  14. -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [5]  
  15. -- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [5]  
  16. -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926 

NF 4.0 出来有一段时间了,只是我比较懒,一直没有测试过这个问题。直到在看到 LINQ to SQL changes in .NET 4.0 其中提及的 Skip(0) 才有此次测试。所以,还在用 3.5 的兄弟们,赶紧升级到 4.0 吧。

原文标题:LINQ to SQL 分页问题

链接:http://www.cnblogs.com/AutumnalRiver/archive/2010/06/13/1757891.html

【编辑推荐】

  1. Linq匿名类型简单概述
  2. Linq随机读取数据浅析
  3. Linq Lambda表达式全面分析
  4. Linq扩展方法简单分析
  5. 初探Linq局部变量类型
责任编辑:彭凡 来源: 博客园
相关推荐

2009-09-18 14:51:19

LINQ TO SQL

2009-09-22 09:31:08

LINQ to SQL

2009-09-14 13:17:51

LINQ to SQLLINQ to SQL

2009-09-17 09:24:57

Linq实现分页

2009-09-18 17:17:58

LINQ模型

2010-08-04 09:55:34

LINQ to SQL

2009-05-11 10:40:36

.NETLINQforeach

2009-09-08 14:45:24

Linq to SQL支持SQL Serve

2009-09-08 17:27:18

LINQ to Dat

2009-09-10 17:44:36

DOM模型INQ模型

2010-06-24 14:49:00

Linux Cat详解

2009-09-11 12:08:09

Linq to SQL

2009-09-16 17:33:16

LINQ TO SQL

2009-09-09 14:40:43

Linq to sql

2009-09-15 17:07:24

Linq To SQL

2009-09-11 12:13:40

LINQ to SQL

2009-09-08 13:16:01

Linq to SQL

2009-09-10 11:29:00

LINQ to SQL

2009-09-18 14:33:37

LINQ to SQLSQL命令

2009-06-15 17:32:09

LINQ更新数据
点赞
收藏

51CTO技术栈公众号