首页 > 编程 > .NET > 正文

asp.net(C#)海量数据表高效率分页算法(不使用存储过程)

2024-07-10 13:11:21
字体:
来源:转载
供稿:网友

首先创建一张表(要求id自动编号):
create table redheadedfile(
id int identity(1,1),
filenames nvarchar(20),
senduser nvarchar(20),
primary key(id)
)
然后我们写入50万条记录:
declare @i int
set @i=1
while @i<=500000
begin
    insert into redheadedfile(filenames,senduser) values('我的分页算法','陆俊铭')
    set @[email protected]+1
end
go
用microsoft visual studio .net 2003创建一张webform网页(本人起名webform8.aspx)
前台代码片段如下(webform8.aspx):
<%@ page language="c#" codebehind="webform8.aspx.cs" autoeventwireup="false" inherits="webapplication6.webform8" %>
<!doctype html public "-//w3c//dtd html 4.0 transitional//en" >
<html>
 <head>
  <title>webform8</title>
  <meta content="microsoft visual studio .net 7.1" name="generator">
  <meta content="c#" name="code_language">
  <meta content="javascript" name="vs_defaultclientscript">
  <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetschema">
 </head>
 <body ms_positioning="gridlayout">
  <form id="form1" method="post" runat="server">
   <asp:datalist id="datalist1" alternatingitemstyle-backcolor="#f3f3f3" width="100%" cellspacing="0"
    cellpadding="0" runat="server">
    <itemtemplate>
     <table width="100%" border="0" cellspacing="0" cellpadding="0">
      <tr>
       <td width="30%"

align="center"><%#databinder.eval(container.dataitem,"filenames")%></td>
       <td width="30%"

align="center"><%#databinder.eval(container.dataitem,"senduser")%></td>
       <td width="30%"

align="center"><%#databinder.eval(container.dataitem,"id")%></td>
      </tr>
     </table>
    </itemtemplate>
   </asp:datalist>
   <div align="center">共<asp:label id="lpagecount" runat="server" forecolor="#ff0000"></asp:label>页/共

<asp:label id="lrecordcount" runat="server" forecolor="#ff0000"></asp:label>记录
    <asp:linkbutton id="fistpage" runat="server"

commandname="0">首页</asp:linkbutton>&nbsp;&nbsp;&nbsp;&nbsp;<asp:linkbutton id="prevpage" runat="server" commandname="prev">

上一页</asp:linkbutton>&nbsp;&nbsp;&nbsp;&nbsp;<asp:linkbutton id="nextpage" runat="server"

commandname="next">下一页</asp:linkbutton>&nbsp;&nbsp;&nbsp;&nbsp;<asp:linkbutton id="lastpage" runat="server"

commandname="last">尾页</asp:linkbutton>&nbsp;&nbsp;&nbsp;&nbsp;当前第<asp:label id="lcurrentpage" runat="server"

forecolor="#ff0000"></asp:label>页&nbsp;&nbsp;&nbsp;&nbsp;跳页<asp:textbox id="gotopage" runat="server" width="30px"

maxlength="5" autopostback="true"></asp:textbox></div>
  </form>
 </body>
</html>
后台代码片段如下(webform8.aspx.cs)
using system;
using system.collections;
using system.componentmodel;
using system.data;
using system.drawing;
using system.web;
using system.web.sessionstate;
using system.web.ui;
using system.web.ui.webcontrols;
using system.web.ui.htmlcontrols;
using system.data.sqlclient;
using system.configuration;

namespace webapplication6
{
 /// <summary>
 /// webform8 的摘要说明。
 /// </summary>
 public class webform8 : system.web.ui.page
 {
  protected system.web.ui.webcontrols.linkbutton fistpage;
  protected system.web.ui.webcontrols.linkbutton prevpage;
  protected system.web.ui.webcontrols.linkbutton nextpage;
  protected system.web.ui.webcontrols.linkbutton lastpage;
  protected system.web.ui.webcontrols.datalist datalist1;
  protected system.web.ui.webcontrols.dropdownlist mydroplist;
  protected system.web.ui.webcontrols.label lpagecount;
  protected system.web.ui.webcontrols.label lrecordcount;
  protected system.web.ui.webcontrols.label lcurrentpage;
  protected system.web.ui.webcontrols.textbox gotopage;
  const int pagesize=20;//定义每页显示记录
  int pagecount,reccount,currentpage,pages,jumppage;//定义几个保存分页参数变量
 
  private void page_load(object sender, system.eventargs e)
  {
   if(!ispostback)
   {
    reccount = calc();//通过calc()函数获取总记录数
    pagecount = reccount/pagesize + overpage();//计算总页数(加上overpage()函数防止有余数造成显示

数据不完整)

    viewstate["pagecounts"] = reccount/pagesize -

modpage();//保存总页参数到viewstate(减去modpage()函数防止sql语句执行时溢出查询范围,可以用存储过程分页算法来理解这句)
    viewstate["pageindex"] = 0;//保存一个为0的页面索引值到viewstate
    viewstate["jumppages"] = pagecount;//保存pagecount到viewstate,跳页时判断用户输入数是否超出页

码范围
    //显示lpagecount、lrecordcount的状态
    lpagecount.text = pagecount.tostring();
    lrecordcount.text = reccount.tostring();
    //判断跳页文本框失效
    if(reccount <= 20)
     gotopage.enabled = false;
    tdatabind();//调用数据绑定函数tdatabind()进行数据绑定运算
   }
  }
        //计算余页
  public int overpage()
  {
   int pages = 0;
   if(reccount%pagesize != 0)
    pages = 1;
   else
    pages = 0;
   return pages;
  }
        //计算余页,防止sql语句执行时溢出查询范围
  public int modpage()
  {
   int pages = 0;
   if(reccount%pagesize == 0 && reccount != 0)
    pages = 1;
   else
    pages = 0;
   return pages;
  }
        /*
   *计算总记录的静态函数
   *本人在这里使用静态函数的理由是:如果引用的是静态数据或静态函数,连接器会优化生成代码,去掉动态重定位项(对

海量数据表分页效果更明显)。
   *希望大家给予意见、如有不正确的地方望指正。
  */
  public static int calc()
  {
   int recordcount = 0;
   sqlcommand mycmd = new sqlcommand("select count(*) as co from redheadedfile",mycon());
   sqldatareader dr = mycmd.executereader();
   if(dr.read())
    recordcount = int32.parse(dr["co"].tostring());
   mycmd.connection.close();
   return recordcount;
  }
        //数据库连接语句(从web.config中获取)
  public static sqlconnection mycon()
  {
   sqlconnection myconnection = new sqlconnection(configurationsettings.appsettings["dsn"]);
   myconnection.open();
   return myconnection;
  }
        //对四个按钮(首页、上一页、下一页、尾页)返回的commandname值进行操作
  private void page_onclick(object sender, commandeventargs e)
  {
   currentpage = (int)viewstate["pageindex"];//从viewstate中读取页码值保存到currentpage变量中进行参数运


            pages = (int)viewstate["pagecounts"];//从viewstate中读取总页参数运算

   string cmd = e.commandname;
   switch(cmd)//筛选commandname
   {
    case "next":
     currentpage++;
     break;
    case "prev":
     currentpage--;
     break;
    case "last":
     currentpage = pages;
     break;
    default:
     currentpage = 0;
     break;
   }
   viewstate["pageindex"] = currentpage;//将运算后的currentpage变量再次保存至viewstate
   tdatabind();//调用数据绑定函数tdatabind()
  }

  private void tdatabind()
  {
   currentpage = (int)viewstate["pageindex"];//从viewstate中读取页码值保存到currentpage变量中进行按钮失

效运算
   pages = (int)viewstate["pagecounts"];//从viewstate中读取总页参数进行按钮失效运算
   //判断四个按钮(首页、上一页、下一页、尾页)状态
   if (currentpage + 1 > 1)
   {
    fistpage.enabled = true;
    prevpage.enabled = true;
   }
   else
   {
    fistpage.enabled = false;
    prevpage.enabled = false;
   }
   if (currentpage == pages)
   {
    nextpage.enabled = false;
    lastpage.enabled = false;
   }
   else
   {
    nextpage.enabled = true;
    lastpage.enabled = true;
   }
            //数据绑定到datalist控件
   dataset ds = new dataset();
   //核心sql语句,进行查询运算(决定了分页的效率:))
   sqldataadapter myadapter = new sqldataadapter("select top "+pagesize+" * from redheadedfile where id

not in(select top "+pagesize*currentpage+" id from redheadedfile order by id asc) order by id asc",mycon());
   myadapter.fill(ds,"news");
   datalist1.datasource = ds.tables["news"].defaultview;
   datalist1.databind();
   //显示label控件lcurrentpaget和文本框控件gotopage状态
   lcurrentpage.text = (currentpage+1).tostring();
   gotopage.text = (currentpage+1).tostring();
   //释放sqldataadapter
   myadapter.dispose();
  }

  #region web 窗体设计器生成的代码
  override protected void oninit(eventargs e)
  {
   //
   // codegen: 该调用是 asp.net web 窗体设计器所必需的。
   //
   initializecomponent();
   base.oninit(e);
  }
  
  /// <summary>
  /// 设计器支持所需的方法 - 不要使用代码编辑器修改
  /// 此方法的内容。
  /// </summary>
  private void initializecomponent()
  {   
   this.fistpage.command += new system.web.ui.webcontrols.commandeventhandler(this.page_onclick);
   this.prevpage.command += new system.web.ui.webcontrols.commandeventhandler(this.page_onclick);
   this.nextpage.command += new system.web.ui.webcontrols.commandeventhandler(this.page_onclick);
   this.lastpage.command += new system.web.ui.webcontrols.commandeventhandler(this.page_onclick);
   this.gotopage.textchanged += new system.eventhandler(this.gotopage_textchanged);
   this.load += new system.eventhandler(this.page_load);

  }
  #endregion
        //跳页代码
  private void gotopage_textchanged(object sender, system.eventargs e)
  {
   try
   {
    jumppage = (int)viewstate["jumppages"];//从viewstate中读取可用页数值保存到jumppage变量中
    //判断用户输入值是否超过可用页数范围值
    if(int32.parse(gotopage.text) > jumppage || int32.parse(gotopage.text) <= 0)
     

response.write("<script>alert('页码范围越界!');location.href='webform8.aspx'</script>");
    else
    {
     int inputpage = int32.parse(gotopage.text.tostring()) - 1;//转换用户输入值保存在int型

inputpage变量中
     viewstate["pageindex"] = inputpage;//写入inputpage值到viewstate["pageindex"]中
     tdatabind();//调用数据绑定函数tdatabind()再次进行数据绑定运算
    }
   }
      //捕获由用户输入不正确数据类型时造成的异常
   catch(exception exp)
   {
    response.write("<script>alert('"+exp.message+"');location.href='webform8.aspx'</script>");
   }
  }
 }
}

大家来试试,效率是不是高了很多?

如有不妥望大家来指正

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表