最近给分页快搞死,记得之前曾经发过修改DWASP分页的方法,后来又写过手工打造的ASP分页,现在进入.NET当然要配合存储过程打造纯手工高性能分页了.
为什么会叫做高性能,为什么要手工打造,不使用.NET现有的分页控件呢?这个还要追溯到我修改DWASP分页的时候,那个我还不怎么懂程序这个东西,只会修修补补,就更不要去谈什么性能问题.当时改的很心烦,接着叫我的私人技术总监张总帮我看看,当时张总就以一种不屑一顾的眼神往着我,说了句话:值得吗?
接着到我手工打造ASP分页,又搞不下去了,张总丢给我一堆.NET的代码:自己研究吧.然后又丢了一句话:用.NET做吧,几句话搞定,不用这个费神.
后来我发现以前的分页都是把整个数据集全部读取后再做分页处理的,一旦数据量过大,处理会十分缓慢,甚至服务器崩溃.然后就是以前的分页不能象游标一样滚动,总是固定在一组里面,不可能实现当前页码在中间的效果.
接着就要说.NET的分页控件了,确实几句话可以搞定,不过缺陷就是我发现的第一个问题,属于把数据全部读出再处理的那种,没有效率,所以终于开始动手,纯手工打造ASP.NET高性能分页.
首先是存储过程,只取出我需要的那段数据,如果页数超过数据总数,自动返回最后一页的纪录:
复制代码 代码如下:
setANSI_NULLSON
setQUOTED_IDENTIFIERON
GO
--=============================================
--Author:Clear
--Createdate:2007-01-30
--Description:高性能分页
--=============================================
AlterPROCEDURE[dbo].[Tag_Page_Name_Select]
--传入最大显示纪录数和当前页码
@MaxPageSizeint,
@PageNumint,
--设置一个输出参数返回总纪录数供分页列表使用
@Countintoutput
AS
BEGIN
SETNOCOUNTON;
DECLARE
--定义排序名称参数
@Namenvarchar(50),
--定义游标位置
@Cursorint
--首先得到纪录总数
Select@Count=count(tag_Name)
FROM[viewdatabase0716].[dbo].[view_tag];
--定义游标需要开始的位置
Set@Cursor=@MaxPageSize*(@PageNum-1)+1
--如果游标大于纪录总数将游标放到最后一页开始的位置
IF@Cursor>@Count
BEGIN
--如果最后一页与最大每次纪录数相等,返回最后整页
IF@Count%@MaxPageSize=0
Set@Cursor=@Count-@MaxPageSize+1
--否则返回最后一页剩下的纪录
ELSE
Set@Cursor=@Count-(@Count%@MaxPageSize)+1
END
--将指针指到该页开始
SetRowcount@Cursor
--得到纪录开始的位置
Select@Name=tag_Name
FROM[viewdatabase0716].[dbo].[view_tag]
orDERBYtag_Name;
--设置开始位置
SetRowcount@MaxPageSize
--得到该页纪录
Select*
From[viewdatabase0716].[dbo].[view_tag]
Wheretag_Name>=@Name
orderBytag_Name
SetRowcount0
END
然后是分页控件(...为省略的生成HTML代码方法):
复制代码 代码如下:
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
usingSystem.Text;
///<summary>
///扩展连接字符串
///</summary>
publicclassExStringBuilder
{
privateStringBuilderInsertString;
privateStringBuilderPageString;
privateintPrivatePageNum=1;
privateintPrivateMaxPageSize=25;
privateintPrivateMaxPages=10;
privateintPrivateCount;
privateintPrivateAllPage;
publicExStringBuilder()
{
InsertString=newStringBuilder("");
}
///<summary>
///得到生成的HTML
///</summary>
publicstringGetHtml
{
get
{
returnInsertString.ToString();
}
}
///<summary>
///得到生成的分页HTML
///</summary>
publicstringGetPageHtml
{
get
{
returnPageString.ToString();
}
}
///<summary>
///设置或获取目前页数
///</summary>
publicintPageNum
{
get
{
returnPrivatePageNum;
}
set
{
if(value>=1)
{
PrivatePageNum=value;
}
}
}
///<summary>
///设置或获取最大分页数
///</summary>
publicintMaxPageSize
{
get
{
returnPrivateMaxPageSize;
}
set
{
if(value>=1)
{
PrivateMaxPageSize=value;
}
}
}
///<summary>
///设置或获取每次显示最大页数
///</summary>
publicintMaxPages
{
get
{
returnPrivateMaxPages;
}
set
{
PrivateMaxPages=value;
}
}
///<summary>
///设置或获取数据总数
///</summary>
publicintDateCount
{
get
{
returnPrivateCount;
}
set
{
PrivateCount=value;
}
}
///<summary>
///获取数据总页数
///</summary>
publicintAllPage
{
get
{
returnPrivateAllPage;
}
}
///<summary>
///初始化分页
///</summary>
publicvoidPagination()
{
PageString=newStringBuilder("");
//得到总页数
PrivateAllPage=(int)Math.Ceiling((decimal)PrivateCount/(decimal)PrivateMaxPageSize);
//防止上标或下标越界
if(PrivatePageNum>PrivateAllPage)
{
PrivatePageNum=PrivateAllPage;
}
//滚动游标分页方式
intLeftRange,RightRange,LeftStart,RightEnd;
LeftRange=(PrivateMaxPages+1)/2-1;
RightRange=(PrivateMaxPages+1)/2;
if(PrivateMaxPages>=PrivateAllPage)
{
LeftStart=1;
RightEnd=PrivateAllPage;
}
else
{
if(PrivatePageNum<=LeftRange)
{
LeftStart=1;
RightEnd=LeftStart+PrivateMaxPages-1;
}
elseif(PrivateAllPage-PrivatePageNum<RightRange)
{
RightEnd=PrivateAllPage;
LeftStart=RightEnd-PrivateMaxPages+1;
}
else
{
LeftStart=PrivatePageNum-LeftRange;
RightEnd=PrivatePageNum+RightRange;
}
}
//生成页码列表统计
PageString.Append(...);
StringBuilderPreviousString=newStringBuilder("");
//如果在第一页
if(PrivatePageNum>1)
{
...
}
else
{
...
}
//如果在第一组分页
if(PrivatePageNum>PrivateMaxPages)
{
...
}
else
{
...
}
PageString.Append(PreviousString);
//生成中间页
for(inti=LeftStart;i<=RightEnd;i++)
{
//为当前页时
if(i==PrivatePageNum)
{
...
}
else
{
...
}
}
StringBuilderLastString=newStringBuilder("");
//如果在最后一页
if(PrivatePageNum<PrivateAllPage)
{
...
}
else
{
...
}
//如果在最后一组
if((PrivatePageNum+PrivateMaxPages)<PrivateAllPage)
{
...
}
else
{
...
}
PageString.Append(LastString);
}
///<summary>
///生成Tag分类表格
///</summary>
publicvoidTagTable(ExDataRowmyExDataRow)
{
InsertString.Append(...);
}
调用方法:
复制代码 代码如下:
//得到分页设置并放入Session
ExRequestmyExRequest=newExRequest();
myExRequest.PageSession("Tag_",newstring[]{"page","size"});
//生成Tag分页
ExStringBuilderTag=newExStringBuilder();
//设置每次显示多少条纪录
Tag.MaxPageSize=Convert.ToInt32(Session["Tag_size"]);
//设置最多显示多少页码
Tag.MaxPages=9;
//设置当前为第几页
Tag.PageNum=Convert.ToInt32(Session["Tag_page"]);
string[][]myNamenValue=newstring[2][]{
newstring[]{"MaxPageSize","PageNum","Count"},
newstring[]{Tag.MaxPageSize.ToString(),Tag.PageNum.ToString()}
};
//调用存储过程
DataTablemyDataTable=mySQL.BatchGetDB("Tag_Page_Name_Select",myNamenValue,"Count");
Tag.DateCount=(int)mySQL.OutputCommand.Parameters["@Count"].Value;
Tag.Pagination();
HeadPage.InnerHtml=FootPage.InnerHtml=Tag.GetPageHtml;
for(inti=0,j=myDataTable.Rows.Count;i<j;i++)
{
Tag.TagTable(newExDataRow(myDataTable.Rows[i]));
}
TagBox.InnerHtml=Tag.GetHtml;
处理页码到Session的方法就不提供了,没有很大关.调用存储过程返回参数和纪录的方法和之前我写的批量数据操作方法差不多的,只需要定义一个输出方式.
目前我想这些代码还会有瑕疵,等项目后期代码审查的时候再强化吧,我想说的一点就是不要被那些拖来拖去的东西迷惑了,那样对自己永远都没有提高,要抱着知其然,知其所以然的态度去做一件事情,对自己的帮助才会明显.