【LINQ】分享:举例证明Linq to Sql的数据库端分页货真价实

我们以前写程序,提到数据库端分页,一般会感觉实现起来蛮麻烦的,尤其是对SQL 2000的DB,要自己写一堆SQL或写个存储过程什么的。而现在如果用VS2008里的Linq查询语法的话,对开发人员来说就变的超级简单了。

在上周五(11月20日) Linq介绍的课程上,大家有讨论到Linq to Sql的延迟执行数据库端分页具体是怎么做到的?我今天用一个小例子测试了一下,分享给大家。

Linq的分页语法如下:

数据源对象集合].Skip((index-1) * pageSize).Take(pageSize)

比如一个显示sys_users表所有记录的Grid,每页显示20条记录,现在要显示第5页数据的话, Linq的写法如下:

var userList = ctx.sys_users.Skip((5-1)*20).Take(20);
  //上面这句的意思也就是查sys_users表,跳过前80条记录,取后面的20条记录
 
现在我们结合下面的几张图片一边Debug,一边从SQL Server Profiler来看看具体的执行过程:
 
我们想要的结果是:查sys_users表中的第3、4条记录。
 
1、当运行到var userList14 = ctx.sys_users.Skip(2).Take(2); 这句时,可以从Profiler看到还没有做任何查询相关的动作。 
 
2、再执行一步,从Profiler看到还是没有做任何查询相关的动作。这就证明var userList14 = ctx.sys_users.Skip(2).Take(2);这句Linq语句只是创建了查询,并没有执行查询,这就是典型的Linq的“延迟执行”,只有当真正用到数据时,才做查询。 
 
3、再执行一步,从Profiler看到还是没有做任何查询相关的动作。
 
4、最后再执行一步,给GridView做DataBind,现在从Profiler看到执行了查询,并且可以看到编译器帮我们把"ctx.sys_users.Skip(2).Take(2)"这句简单的Linq查询语句转化为较复杂的SQL查询语句。
 
生成的SQL语句为:
exec sp_executesql N'SELECT [t1].[user_id], [t1].[first_name], [t1].[last_name], [t1].[age], [t1].[birth_date], [t1].[email], [t1].[sex]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[user_id], [t0].[first_name], [t0].[last_name], [t0].[age], [t0].[birth_date], [t0].[email], [t0].[sex]) AS [ROW_NUMBER], [t0].[user_id], [t0].[first_name], [t0].[last_name], [t0].[age], [t0].[birth_date], [t0].[email], [t0].[sex]
    FROM [dbo].[sys_users] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]
',N'@p0 int,@p1 int',@p0=2,@p1=2
 
查询结果为: 
从上面的运行情况来看,应该可以基本了解Linq的延迟执行数据库端分页的执行原理了吧。
 
另外要说明两点
1、上面是针对SQL Server 2005做的测试,生成的SQL语句主要用了ROW_NUMBER这个新特性来做的分页。而如果是SQL Server 2000的话,因为没有ROW_NUMBER,所以生成的SQL语句有些不同,还是用TOP来做分页,SQL 2000中生成的SQL大概如下:
SELECT TOP 2 [t1].[user_id][t1].[first_name][t1].[last_name][t1].[age][t1].[birth_date][t1].[email][t1].[sex]
FROM [dbo].[sys_users] AS [t1]
WHERE NOT (EXISTS(
    
SELECT NULL AS [EMPTY]
    
FROM (
        
SELECT TOP 2 [t2].[user_id]
        
FROM [dbo].[sys_users] AS [t2]
        ) 
AS [t3]
    
WHERE [t1].[user_id] = [t3].[user_id]
    ))
可以参考:http://www.cnblogs.com/greater/archive/2008/06/22/1227453.html
 
2、另外要说明一点,在Debug过程中,如果即时查看Linq查询语句的结果视图,会使得Linq查询立即执行。还用上面的例子来看,我在执行到第二步时,去看了一下userList14这个变量的值,就导致了执行查询,如下图所示:
 
如果大家有其它什么问题,欢迎提出,大家一起探讨。

posted on 2009-11-24 17:18  Sammy  阅读(433)  评论(0编辑  收藏  举报

导航