在一个B/S项目中或多或少的都有些需要分页的页面,例如:订单查询,数据统计报表什么的.如果你手下的项目中这样的分页模块特别多,你又如何快速而且非常完美的来完成任务呢?
在园子里面有不少园友写过如何提高编码效率相关文章,都不错,有的就提到了分页控件的开发应用,控件最大的特点就是
功能复用,减少重复代码,从而提高开发人员的效率.有的园友在分页控件开发时把数据源一起给绑定上了,具体怎样实现我并没太多研究,并不是我不认同这种方式,只是我觉的我的方法更加适合我.
同样我也是利用分页控件来开发,我的分页控件只起到分页导航功能,它主要负责
显示分页信息,和具体的数据源没有任何关系,无论是返回DataTable,DataSet,泛型实体集等等。它最大的特点就是分页导航功能和数据源解藕,功能更加灵活。
下面就分享下我个人的做法,不妥之处望指教。
第一:本文并是把分页控件开发做为重点,有兴趣的朋友可以到我的文章中查找,控件开发(8) (RSS) 这里就先帖图:
图一为最终运行的效果图:
图二:为分页控件的相关属性。此控件分页方式分为url分页(例如:default.aspx?page=1),回发式分页。
第二:有了分页导航控件,接下来就是取得数据记录了。
1:数据的最底层:创建查询SQL,这里以一个比较常见的分页存储过程来完成,但又有它与众不同的地方.本人就不详细的说明这个存储过程的用法了,因为所有的说明在里面都有注释。上面的SQL和网上大家看到的通用分页存储过和差不多,主要是利用sql2005的row_number(),它接收页面记录数,索引页,查询条件,排序条件最终返回具体某一页的数据,以及记录总数等。
它与变通分页存储过程最大的不同就是:开发人员对于具体查询部分可以任意写,只是输入参数和返回参数相对固定而已。这点有点类似.net中的模块模式,哈哈,说的远了。
Code
--查询学生信息
create proc [dbo].[proc_studentInfo]
@iRowCount int, --定义一页显示的数据行
@iPageNumber int ,--定义当前面的索引
@sCondition varchar(200),--设置条件
@sCompositor varchar(50),--设置排序方式
@pageCount int out,--返回页面总数
@recordCount int out, --返回记录总数
@iNextPageNumber int out --定义下一页的索引
as
begin
declare @strSql varchar(8000)
declare @strDeleteTemTable varchar(500)
--取得记录总数
declare @strSql2 nvarchar(4000) --查询记录语句变量
--取得记录总数变量字符串
--取得记录总数
set @strSql2='
select @recordCount=count(*) from student
where 1=1 '
if len(@sCondition)>0
begin
set @strSql2=@strSql2+@sCondition
end
print @strSql2
execute sp_executesql @strSql2, N'@recordCount int output',@recordCount output
--取得页面总数
if @recordCount%@iRowCount=0
begin
set @pageCount=@recordCount/@iRowCount
end
if @recordCount%@iRowCount<>0
begin
set @pageCount=@recordCount/@iRowCount+1
end
set @strSql='
select * into #tem from (
select *,
row_number() over(order by ID desc) as rowNum
from student
where 1=1 '
declare @getDataSet varchar(4000)
set @getDataSet=
') as tbl2
select * from #tem
where rowNum between '+cast((@iRowCount*@iPageNumber+1) as varchar)+
' and '+cast((@iRowCount*(@iPageNumber+1)) as varchar)
set @strDeleteTemTable=
' --删除临时表
drop table #tem'
if len(@sCondition)>0
begin
set @strSql=@strSql+@sCondition+@getDataSet+@sCompositor+@strDeleteTemTable
end
else
begin
set @strSql=@strSql+@getDataSet+@sCompositor+@strDeleteTemTable
end
print @strSql
exec(@strSql)
--取得下一页的索引
set @iNextPageNumber =@iPageNumber+1
end
/**//*
declare @pageCount int--返回页面总数
declare @recordCount int --返回记录总数
declare @iNextPageNumber int --定义下一页的索引
declare @sCondition varchar(200)--设置条件
declare @sCompositor varchar(50)--设置排序方式
exec proc_studentInfo 10,0,'','',
@pageCount out,@recordCount out ,@iNextPageNumber out
*/
2:有了查询语句,然后就是在.net环境下封装数据供客户端调用:
Code
/**//// <summary>
/// 根据存储过程名称,搜索条件和表名取得记录集(具有搜索功能)
/// by jiangmin 08-09-20
/// <param name="iRowCount">每页数据数据量</param>
/// <param name="iPageNumber">当前索引页,从0开始</param>
/// <param name="procName">存储过程名称</param>
/// <param name="sCondition">查询条件,以 and 开始,例如 : and sUserName='张三'</param>
/// <param name="strsCompositor">如何排序 例如:order by sUserName</param>
/// <param name="pageCount">查询总记录页数</param>
/// <param name="recordCount">记录总数</param>
/// <param name="iNextPageNumber">下一页的索引数</param>
/// </summary>
/// <returns></returns>
public static DataTable getAll_Information(int iRowCount, int iPageNumber, string procName, string sCondition, string strsCompositor, out int pageCount, out int recordCount, out int iNextPageNumber)
{
数据处理和实现#region 数据处理和实现
DataTable dt = new DataTable();
DataSet ds = new DataSet();
SqlParameter[] cmdParms =
{
new SqlParameter ("@iRowCount", iRowCount ),
new SqlParameter ("@iPageNumber", iPageNumber ),
new SqlParameter ("@sCondition", sCondition ),
new SqlParameter ("@sCompositor", strsCompositor ),
new SqlParameter ("@pageCount",SqlDbType.Int,4 ),
new SqlParameter ("@recordCount", SqlDbType.Int,4 ),
new SqlParameter ("@iNextPageNumber",SqlDbType.Int,4)
};
cmdParms[4].Direction = ParameterDirection.Output;
cmdParms[5].Direction = ParameterDirection.Output;
cmdParms[6].Direction = ParameterDirection.Output;
ds = SqlHelper.ExecuteDataSet(CommandType.StoredProcedure, procName , cmdParms);
pageCount = (int)cmdParms[4].Value;
recordCount = (int)cmdParms[5].Value;
iNextPageNumber = (int)cmdParms[6].Value;
dt = ds.Tables[0];
#endregion
return dt;
}
3:接下来就是客户端绑定数据的操作了,为了说明方便,这里就以一个GridView 来节约时间了。
第一: 页面HTML:
Code
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
<br />
<cc1:WebCustomControlPager ID="WebCustomControlPager1" runat="server">
<CustomInfoSection CustomInfoTextAlign="NotSet" currentPageText="Page:" sRecordCountText="Total:" ShowCustomInfo="Never"></CustomInfoSection>
<PagerText goFirstText="首 页" PrevPageText="&lt;&lt;上一页" NextPageText="下一页&gt;&gt;" LastPageText="尾 页" sGoText="Go" alreadyaFirstPageText="已经是第一页了" alreadyLastPageText="已经是最后一页了"></PagerText>
<CustomPager IsCustomStyle="False" iRecordCount="1" iRowsCount="10" iPrevCount="5"
iNextCount="5" IsInput="True" UrlPaging="True" UrlPageIndexName="page"
IsDisplayFirstText="True" IsDisplayLastText="True"></CustomPager>
</cc1:WebCustomControlPager>
第二:后台代码:
Code
BLL_getStudentInfo _getStudentInfo = new BLL_getStudentInfo();
//当前索引页
int iPageIndex = 0;
if (Request.QueryString["page"] != null && Request.QueryString["page"] != "")
{
int.TryParse(Request.QueryString["page"].ToString().Trim().Replace(",",""), out iPageIndex);
iPageIndex = iPageIndex - 1;
}
//页面总数
int pageCount = 1;
//总记录数
int iRecordCount = 1;
//下一页索引
int iNextPageIndex = 1;
//每页10条记录
int iPageSize = 10;
DataTable dr = _getStudentInfo.BLL_StudentInfo(iPageSize , iPageIndex, "proc_studentInfo", "", " order by ID desc", out pageCount, out iRecordCount, out iNextPageIndex);
this.GridView1.DataSource = dr;
this.GridView1.DataBind();
this.WebCustomControlPager1.CustomPager.iRecordCount = iRecordCount;
this.WebCustomControlPager1.CustomPager.iRowsCount = iPageSize ;
第三: 最终的效果图:图三:
从上面的所有过程来看,你要做的工作是什么呢?
第一:把模板分页存储过程中具体查询语句修改下,例如关联其它表操作等等。
第二:在业务需求页面中引用分页控件及数据绑定控件。
第三:调用通用查询方法,输入每页记录数,索引页,存储过程名称,查询条件,排序条件查询出记录集。
第四:设置分页控件相关参数,最重要的是每页记录数和记录总数,其它的可接收默认值。
这样一个分页操作就基本完成,这就是我对于分页的处理过程,大家在分页时有什么高见不妨分享下。
优点:
1:开发员直接编码部分少;
2:分页样式统一,管理方便;
3:分页控件与数据库解藕,绑定数据方式灵活.
缺点:
1:优点2也就是它的缺点,全站统一分页样式,略显单调,不过可自定义控件样式.
2:如果没有update pannel的支持,要想实现无刷新分页有一定的困难.