• 【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]
        ))
     
    2、另外要说明一点,在Debug过程中,如果即时查看Linq查询语句的结果视图,会使得Linq查询立即执行。还用上面的例子来看,我在执行到第二步时,去看了一下userList14这个变量的值,就导致了执行查询,如下图所示:
     
    如果大家有其它什么问题,欢迎提出,大家一起探讨。
  • 相关阅读:
    Mysql的表名/字段名/字段值是否区分大小写
    20个PHP程序性能优化的方法
    PHP中大括号用法
    PHP伪类型和伪变量
    PHP中关于取模运算及符号
    PHP之array_flip()方法
    PHP之implode()方法
    PHP中is_null()方法
    原型模式(Prototype)
    适配器模式
  • 原文地址:https://www.cnblogs.com/songsh96/p/1609678.html
Copyright © 2020-2023  润新知