ASP.NET高效率的分页算法程序代码

作者:袖梨 2022-06-25

 使用ASP.NET开发web程序时,经常会遇到数据列表页需要分页的问题。在ASP.NET里,分页可以通过绑定数据控件实现,如GridView、DataList、Repeater、ListView等这些数据控件都可以实现分页效果。它们之间的一些对比:

    GridView:开发效率高,自带分页、排序、但占用资源高。
    DataList:分页和排序需要手动编码,分页需要使用 PagedDataSource类实现。
    Repeater:不提供任何布局,开发周期长。

    注意,使用这些控件的时候,ViewState功能必须打开(即 EnableViewState="true" 在NET里,默认是打开的),因为如果关闭了ViewState视图状态,在点击下一页这些跳转按钮时,.net页面是记不住当前状态的。

    但是,重点来了:
    这些使用控件的分页方法基本是采用了javascript的方法实现的跳转:
    比如 DataList 配合 PagedDataSource类实现的代码如下:
  

 代码如下 复制代码
  下一页
    GridView自带的分页代码如下:
    第2页

    而我们知道,作为web网站程序开发,seo/seo.html" target="_blank">搜索引擎对页面的(前台)js的链接并不敏感,也不会抓取和索引js里的链接,这就会造成一个严重的情况,那就是列表页从第二页开始,都无法抓取并索引,大量网页无法出现在搜索引擎的结果页里。

    因此,飘易设计了一个比较通用的高效率的asp.net分页算法的实现,实现方法如下:

    在 default.aspx 前台页面里放入代码(注意,必须添加  runat="server" 标记):


    在 default.aspx.cs 后台代码页面里编写代码:

 代码如下 复制代码

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;

public partial class _Default: System.Web.UI.Page
{
    comClass CC = new comClass();//实例化

    protected void Page_Load(object sender, EventArgs e)
    {//初始化
        if (!IsPostBack)
        {
            string html = getListData();
            divlist.InnerHtml = html;
        }
    }

    public static bool IsNum(String str)
    {//判断是否是ASCII纯数字
        if (str == null || str == "") return false;
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] < '0' || str[i] > '9')
                return false;
        }
        return true;
    }

    public string getListData()
    {//绑定数据
        string html = "";
        SqlConnection conn = CC.getConn();
        conn.Open();
        SqlCommand cmd;
        SqlDataReader dr;
        try
        {
            int page = 1;
            string page_get = Request["page"]; //获取当前页
            if (IsNum(page_get)) page = Convert.ToInt32(page_get);
            int pagesize = 5; //每页多少个
            int TotalRecords, TotalPages;

            //总记录数
            cmd = new SqlCommand("select count(*) from data ", conn);
            dr = cmd.ExecuteReader();
            dr.Read();
            TotalRecords = Int32.Parse(dr[0].ToString());
            dr.Close();
            cmd.Dispose();
            //总页数
            if (TotalRecords % pagesize == 0) TotalPages = TotalRecords / pagesize;
            else TotalPages = TotalRecords / pagesize + 1;
            //当前页
            if (page < 1) page = 1;
            if (page > TotalPages) page = TotalPages;

            //---核心分页算法---
            string sql = "select top " + pagesize + " * from data order by id desc";
            if (page > 1) sql = "select top " + pagesize + " * from data where id<(SELECT Min(id) FROM (SELECT TOP " + pagesize * (page - 1) + " id FROM data ORDER BY id desc) AS T) order by id desc";
            cmd = new SqlCommand(sql, conn);
            dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                html += dr["id"].ToString() + "、" + dr["title"].ToString() + "
";
            }
            dr.Close();
            cmd.Dispose();

            //分页代码
            string cfile = Request.Path; //当前请求的虚拟路径
            string pagestr = "rn

首页 ";
            for (int i=1; i<=TotalPages ; i++ )
            {
                if (i == page) pagestr += " " + i + " ";
                else
                {
                    if (Math.Abs(page - i) < 8)
                    {
                        if (i == 1) pagestr += " " + i + " ";
                        else pagestr += " " + i + " ";
                    }
                }
            }
            pagestr += " 尾页 ";
            pagestr += " 第" + page + "/" + TotalPages + "页, 总共" + TotalRecords + "条
";
            html += pagestr;
        }
        catch (Exception ex) { html = "异常错误:" + ex.ToString(); }
        finally { conn.Close(); }
        return html;
    }


}


 

存储过程分页法

OK,我们首先创建一数据库:data_Test,并在此数据库中创建一表:tb_TestTable

1create database data_Test  --创建数据库data_Test
 2GO
 3use data_Test
 4GO
 5create table tb_TestTable   --创建表
 6(
   id int identity(1,1) primary key,
   userName nvarchar(20) not null,
   userPWD nvarchar(20) not null,
   userEmail nvarchar(40) null
11)
12GO


然后我们在数据表中插入2000000条数据:

1--插入数据
 2set identity_insert tb_TestTable on
 3declare @count int
 4set @count=1
 5while @count<=2000000
 6begin 
   insert into tb_TestTable(id,userName,userPWD,userEmail) values(@count,'admin','admin888','[email protected]')
   set @count=@count+1
 9end
10set identity_insert tb_TestTable off

下面是2分法使用select max的代码,已相当完善。

 代码如下 复制代码

1--/*-----存储过程 分页处理 孙伟 2005-03-28创建 -------*/
  2--/*-----存储过程 分页处理 浪尘 2008-9-1修改----------*/
  3--/*----- 对数据进行了2分处理使查询前半部分数据与查询后半部分数据性能相同 -------*/
  5alter PROCEDURE proc_paged_2part_selectMax
  6(
  7@tblName     nvarchar(200),        ----要显示的表或多个表的连接
  8@fldName     nvarchar(500) = '*',    ----要显示的字段列表
  9@pageSize    int = 10,        ----每页显示的记录个数
 10@page        int = 1,        ----要显示那一页的记录
 11@fldSort    nvarchar(200) = null,    ----排序字段列表或条件
 12@Sort        bit = 0,        ----排序方法,0为升序,1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记)--程序传参如:' SortA Asc,SortB Desc,SortC ')
 13@strCondition    nvarchar(1000) = null,    ----查询条件,不需where
 14@ID        nvarchar(150),        ----主表的主键
 15@Dist                 bit = 0,           ----是否添加查询字段的 DISTINCT 默认0不添加/1添加
 16@pageCount    int = 1 output,            ----查询结果分页后的总页数
 17@Counts    int = 1 output                ----查询到的记录数
 18)
 19AS
 20SET NOCOUNT ON
 21Declare @sqlTmp nvarchar(1000)        ----存放动态生成的SQL语句
 22Declare @strTmp nvarchar(1000)        ----存放取得查询结果总数的查询语句
 23Declare @strID     nvarchar(1000)        ----存放取得查询开头或结尾ID的查询语句
 25Declare @strSortType nvarchar(10)    ----数据排序规则A
 26Declare @strFSortType nvarchar(10)    ----数据排序规则B
 28Declare @SqlSelect nvarchar(50)         ----对含有DISTINCT的查询进行SQL构造
 29Declare @SqlCounts nvarchar(50)          ----对含有DISTINCT的总数查询进行SQL构造
 31declare @timediff datetime  --耗时测试时间差
 32select @timediff=getdate()
 34if @Dist  = 0
 35begin
   set @SqlSelect = 'select '
   set @SqlCounts = 'Count(*)'
 38end
 39else
 40begin
   set @SqlSelect = 'select distinct '
   set @SqlCounts = 'Count(DISTINCT '+@ID+')'
 43end
 45
 46if @Sort=0
 47begin
   set @strFSortType=' ASC '
   set @strSortType=' DESC '
 50end
 51else
 52begin
   set @strFSortType=' DESC '
   set @strSortType=' ASC '
 55end
 57
 59--------生成查询语句--------
 60--此处@strTmp为取得查询结果数量的语句
 61if @strCondition is null or @strCondition=''     --没有设置显示条件
 62begin
   set @sqlTmp =  @fldName + ' From ' + @tblName
   set @strTmp = @SqlSelect+' @Counts='+@SqlCounts+' FROM '+@tblName
   set @strID = ' From ' + @tblName
 66end
 67else
 68begin
   set @sqlTmp = + @fldName + 'From ' + @tblName + ' where (1>0) ' + @strCondition
   set @strTmp = @SqlSelect+' @Counts='+@SqlCounts+' FROM '+@tblName + ' where (1>0) ' + @strCondition
   set @strID = ' From ' + @tblName + ' where (1>0) ' + @strCondition
 72end
 74----取得查询结果总数量-----
 75exec sp_executesql @strTmp,N'@Counts int out ',@Counts out
 76declare @tmpCounts int
 77if @Counts = 0
   set @tmpCounts = 1
 79else
   set @tmpCounts = @Counts
 82    --取得分页总数
   set @pageCount=(@tmpCounts+@pageSize-1)/@pageSize
 85    /**//**//**//**当前页大于总页数 取最后一页**/
   if @page>@pageCount
       set @page=@pageCount
 89    --/*-----数据分页2分处理-------*/
   declare @pageIndex int --总数/页大小
   declare @lastcount int --总数%页大小 
 93    set @pageIndex = @tmpCounts/@pageSize
   set @lastcount = @tmpCounts%@pageSize
   if @lastcount > 0
       set @pageIndex = @pageIndex + 1
   else
       set @lastcount = @pagesize
100    --//***显示分页
   if @strCondition is null or @strCondition=''     --没有设置显示条件
   begin
       if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理
           begin 
               if @page=1
                   set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName                        
                       +' order by '+ @fldSort +' '+ @strFSortType
               else
               begin
                   if @Sort=1
                   begin                    
                   set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' <(select min('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                       +' order by '+ @fldSort +' '+ @strFSortType
                   end
                   else
                   begin
                   set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' >(select max('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                       +' order by '+ @fldSort +' '+ @strFSortType 
                   end
               end    
           end
       else
           begin
           set @page = @pageIndex-@page+1 --后半部分数据处理
               if @page <= 1 --最后一页数据显示                
                   set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@lastcount as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType 
               else
                   if @Sort=1
                   begin
                   set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' >(select max('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                       +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType
                   end
                   else
                   begin
                   set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' <(select min('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                       +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType 
                   end
           end
   end
150    else --有查询条件
   begin
       if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理
       begin
               if @page=1
                   set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName                        
                       +' where 1=1 ' + @strCondition + ' order by '+ @fldSort +' '+ @strFSortType
               else if(@Sort=1)
               begin                    
                   set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' <(select min('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' where (1=1) ' + @strCondition +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                       +' '+ @strCondition +' order by '+ @fldSort +' '+ @strFSortType
               end
               else
               begin
                   set @strTmp=@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' >(select max('+ @ID +') from ('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' where (1=1) ' + @strCondition +' order by '+ @fldSort +' '+ @strFSortType+') AS TBMinID)'
                       +' '+ @strCondition +' order by '+ @fldSort +' '+ @strFSortType 
               end           
       end
       else
       begin 
           set @page = @pageIndex-@page+1 --后半部分数据处理
           if @page <= 1 --最后一页数据显示
                   set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@lastcount as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where (1=1) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType                     
           else if(@Sort=1)
                   set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' >(select max('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' where (1=1) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                       +' '+ @strCondition+' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType    
           else
                   set @strTmp=@SqlSelect+' * from ('+@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' from '+@tblName
                       +' where '+@ID+' <(select min('+ @ID +') from('+ @SqlSelect+' top '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @ID +' from '+@tblName
                       +' where (1=1) '+ @strCondition +' order by '+ @fldSort +' '+ @strSortType+') AS TBMaxID)'
                       +' '+ @strCondition+' order by '+ @fldSort +' '+ @strSortType+') AS TempTB'+' order by '+ @fldSort +' '+ @strFSortType            
       end    
   end
191------返回查询结果-----
192exec sp_executesql @strTmp
193select datediff(ms,@timediff,getdate()) as 耗时
194--print @strTmp
195SET NOCOUNT OFF
196GO

相关文章

精彩推荐