点: 1、不必使用存储过程就可以达到高效率的分页效果。 2、使用两种(或者多种)分页算法,来达到效率和通用的完美统一。 3、按需所取。如果一页显示20条记录,那么分页控件只会从数据库里提取20条数据。 4、支持查询条件,您可以很方便的添加查询条件,实现复杂的检索功能。 6、在百万级数据下也有很好的表现,当然需要合理设置索引。 7、使用方便,只需要设置几个属性就可以,不必处理分页时产生的事件。 8、支持多种显示数据的控件。
温馨提示:
asp.net分页控件已经升级了,基于.net2.0 ,支持多种数据库。
正式命名为:QuickPager Asp.net 2.0 分页控件。
网站:www.natureFW.com
下载:http://www.naturefw.com/down/List1.aspx
在线演示:http://demo.naturefw.com
上一篇随笔:
我的分页控件(未完,待续)——控件件介绍及思路
一、分页控件的工作层次
如果按照三层的划分方式来说,应该算作工作在 UI层 和 逻辑层。
在分页控件内部会调用“数据访问函数库”来访问数据库,得到记录集之后再绑定到指定的显示数据的控件。
当然这里只是打个比方,我并没有按照三层的规范来写这个分页控件,我的目的只是想少写点代码。
二、适用范围
目前适用于 vs2003 和 SQL Server 2000
因为是在这两个环境下开发的,尤其是对于 SQL Server 2000 进行了一些优化。
当然也是可以在 vs2005 和 SQL Server 2005 下使用,只是没有针对 05系列 进行优化。
可以在vs2005的项目里引用 分页控件的dll文件,但是可能需要在电脑上安装 .net1.1 的框架。
三、优点
1、不必使用存储过程就可以达到高效率的分页效果。
2、使用两种(或者多种)分页算法,来达到效率和通用的完美统一。当然也可以使用不同的算法应对不同的数据库。
3、按需所取。如果一页显示20条记录,那么分页控件只会从数据库里提取20条数据。
4、支持查询条件,您可以很方便的添加查询条件,实现复杂的检索功能。
5、利用ViewState 来保存一些信息,节省服务器的资源。
比如在第一次显示数据的时候会统计总记录数,然后把总记录数保存到ViewState里面,当点击下一页的时候不用重新统计。
还有其他的信息也会保存到 ViewState 里面。
6、在百万级数据下也有很好的表现,下面有测试数据,不信的话,可以下载demo亲自测试。
7、使用方便,只需要设置几个属性就可以,不必处理分页时产生的事件。
8、支持多种显示数据的控件,比如DataGrid、DataList、Reapeter、DropDownList等。只要是能够使用DataTable绑定的控件都支持。
9、可以使用键盘快速翻页。
“左方向”键:向前翻页;
“右方向”键:向后翻页;
PageUp键:上一页;
PageDown键:下一页;
Home:首页;
End:末页;
数字键:1到10页,0表示第十页
四、缺点
1、多表联合查询的时候需要使用视图。就是要先建立一个视图。
2、第一种分页算法不要求数据表一定要有主键,但是第二种分页算法要求表必须有主键,而且不能使联合主键。
3、不能很灵活的应对多种数据库。
4、内部代码比较混乱,05年底写的,一直想整理,但是都没有开始整理,只是做了小的升级和修改bug。
五、使用方法
先在 Page_Load 设置显示数据的控件 比如 DataGrid,
private void Page_Load(object sender, System.EventArgs e)
{
//设置显示数据的控件,注意,不是ID而是实例
myPage.PubShowDataObject = this.DG ;
if (!Page.IsPostBack)
{
SetPage();
}
}
然后根据情况设置分页控件的其它属性
第一种分页算法的属性设置。单字段排序,且排序字段没有重复记录
private void SetPage()
{
//简单的分页方式
//只能有一个排序字段,且排序字段的值没有重复的。
myPage.SqlTableNames = "Products"; //要显示数据的表名或者视图名
myPage.SqlColumns = "*"; //要显示字段
myPage.SqlOrderColumn = "ProductID"; //排序字段
myPage.SqlOrderColumnKind = "int"; //排序字段的类型。可选项:"int"、"string"、"datetime"、"float"
myPage.SqlPageSize = 5; //一页显示的记录数
myPage.IsOrderDesc = true; //倒序显示记录
//查询条件
myPage.SqlQuery = "";
//查询条件,回发后再次执行 myPage.CreateQuery() 的时候,会把 SetQuery 添加到 SqlQuery 里。
myPage.SetQuery = "";
myPage.CreateQuery(); //生成查询语句 回发后生成的查询语句可以保存。
myPage.BindFirstPage(); //显示第一页的数据
}
第二种分页算法的属性设置。多排序字段,或者是单排序字段且排序字段有重复记录(其实是转换成了多排序字段的情况)。
private void SetPage2()
{
//多排序字段的分页方式
//支持多字段排序。
myPage.SetSQLKind = "2"; //设置分页算法
myPage.SqlTableNames = "Products"; //要显示数据的表名或者视图名
myPage.SqlColumns = "*"; //要显示字段
myPage.SqlPowerIDColumn = "ProductID"; //主键字段名称
//一个排序字段,且有重复值的情况,不能把主键字段放在下面的两个属性里面
myPage.SqlPowerOrderColumnA = "UnitPrice ,ReorderLevel desc"; //排序字段 按开始日期正序
myPage.SqlPowerOrderColumnB = "UnitPrice desc,ReorderLevel "; //这里要设置为上面的字段的相反的排序方式。
//多个排序字段的情况
myPage.SqlPowerOrderColumnA = "UnitPrice"; //排序字段 按开始日期正序
myPage.SqlPowerOrderColumnB = "UnitPrice desc"; //这里要设置为上面的字段的相反的排序方式。
myPage.SqlPowerHasMoreValue = true; //最后一个排序字段是否有重复值
myPage.SqlPageSize = 5; //一页显示的记录数
myPage.SqlQuery = ""; //查询条件,回发后该属性失效
myPage.SetQuery = ""; //查询条件,回发后该属性可以保存
myPage.CreateQuery(); //生成查询语句 回发后生成的查询语句可以保存。
myPage.BindFirstPage(); //显示第一页的数据
}
查询情况,点击查询按钮后需要做的事情。这里只是作了一个演示,可以增加更多的查询条件
实现查询功能#region 实现查询功能
private void Btn_Search_Click(object sender, System.EventArgs e)
{
//Response.Write(myPage.SqlQuery); 输出查询条件
//查询数据
string query = ""; //保存查询条件 where 后面的sql语句
string tmp = ""; //保存查询关键字
//第一个查询条件
tmp = this.Txt_ProductName.TextTrimNone ;
if (tmp.Length > 0)
query = "ProductName like '%" + tmp + "%'";
//其他的查询条件
tmp = Txt_UnitPrice1.TextTrimNone ;
string tmp2 = Txt_UnitPrice2.TextTrimNone ;
if (tmp.Length > 0)
{
判断是否是数字#region 判断是否是数字
if (!Functions.IsInt(tmp))
{
Functions.PageRegisterAlert(Page,("请输入数字"));
return;
}
if (!Functions.IsInt(tmp2))
{
tmp2 = tmp;
}
#endregion
if (query.Length ==0)
query = "UnitPrice between " + tmp + " and " + tmp2;
else
query += " and UnitPrice between " + tmp + " and " + tmp2;
}
myPage.SqlQuery = query; //查询条件,回发后该属性失效
myPage.CreateQuery(); //生成查询语句 回发后生成的查询语句可以保存。
myPage.BindFirstPage(); //显示第一页的数据
}
#endregion
还有两个事件,一般情况下不用处理,这里只是记录使用的时间。
private void myPage_DataBindBefore(object s, System.EventArgs e)
{
//获取记录前的事件
dt1 = DateTime.Now;
}
private void myPage_DataBindAfter(object s, System.EventArgs e)
{
//绑定控件后的事件
DateTime dt2 = DateTime.Now;
TimeSpan ts = dt2 - dt1;
Response.Write(ts.Minutes + "分");
Response.Write(ts.Seconds + "秒");
Response.Write(ts.Milliseconds + "毫秒");
}
六、分页控件源代码和演示代码下载
http://www.cnblogs.com/jyk/archive/2008/04/25/1170979.html
需要修改 web.config 里面的连接字符串。
七、核心代码
因为是分页控件,所以呢, 核心代码就是如何分页,也就是分页的算法,使用哪个SQL语句既可以达到很高的效率,又可以满足排序、查询的需求。
这里针对sql Server 2000 进行了优化,采用两种分页算法。
第一种算法针对的是一个排序字段,且排序字段没有重复值的情况。
第二种算法针对的是多排序字段的情况。
第一种算法的SQL语句
declare @col int
set @col =1
select top {PageSize * (PageIndex - 1) + 1} @col = [排序字段] from TableName
select top PageSize * from TableName where [排序字段] >= @col
我知道排序字段不一定都是 int类型的,所以在 第一种算法的时候需要设置一个属性
myPage.SqlOrderColumnKind = "int"; 通过这个属性来修改上面的SQL语句。
第二种算法的SQL语句
对于这种算法你可能会说,在显示最后一页的时候有问题,这个我也发现了,并且在分页控件里面对最后一页作了修改,已经修证了这个bug。
select [*] from [Table] where [ID] in (
select top 10 [ID] from
(
select top 20 [ID] ,AddedDate from [Table]
order by [AddedDate] desc,[ID]
) as aa order by [AddedDate] ,[ID] desc
)order by [AddedDate] desc,[ID]
八、海量数据测试结果
cpu:xp3000+ 单核
内存:DDR2 1G
硬盘:串口
测试用数据库:SQL Server2000 里的 Northwind 数据库里的 Products 表,就是自带的那个。
显示数据的控件:DataGrid 自动填充字段的方式。
记录数:2523136条。
一页显示5条记录。
//分页算法1 单字段排序,且排序字段是聚集索引。
//1000 页以内 15毫秒
//10000页以内 30毫秒
//50000页以内 100多毫秒
//100000页以内 200多毫秒
//最后几页 第一次跳转到 4秒多
//最后几页 连续向前翻页 1秒156毫秒
//页号大范围跳转的时候需要的时间比较长,但是也小于1秒,同时SQL Server 占用的内存有所增加 120M。最后几页时达到320M
===================================================================
以下是多排序字段的分页情况,排序字段是 UnitPrice,ProductID
//分页算法2 无索引 首页 8秒187毫秒 。
//10 页以内 2秒812毫秒
//速度太慢下面的就不测试了
//分页2 非聚集索引 UnitPrice 首页 468毫秒
//10 页以内 2秒671毫秒
//速度太慢下面的就不测试了
//分页算法2 非聚集索引 UnitPrice,ProductID 首页 500毫秒
//10 页以内 2秒796毫秒
//100页以内 4秒796毫秒
//速度太慢下面的就不测试了
//分页算法2 非聚集索引 UnitPrice,ProductID desc 首页 500毫秒
//10 页以内 0-15毫秒
//100页以内 15-46毫秒
//1000页以内 31-62毫秒
//10000页以内 100毫秒左右
//50000页以内 400-500毫秒
//100000页以内 900毫秒左右
//最后几页 第一次跳转到 4秒421毫秒
//最后几页 连续向前翻页 4秒375毫秒
//页号大范围跳转的时候需要的时间比较长,但是也小于1秒,
//这回SQL Server 占用的内存增加幅度不大 120M左右
可见设置好索引对于海量数据的分页的重要性