用DataGrid控件分页显示记录
在创建链接和命令对象之后就要把返回的记录显示出来。DataGrid控件是ASP.NET中功能最强大也是最复杂的数据控件,可以用它来显示和格式化数据表的数据,它除了内建的数据表现和方法之外,还允许用户自己定义表现形式。分页技术为用户可管理的数据查找提供方便。
1、DataGrid内建分页技术原理
DataGrid内建分页技术很容易实现,但数据量很大时,它的方便性是以牺牲性能为代价的。如果一个用户只要求100个页面中每页显示25条记录的第8页的结果集,服务器只需要发送第175-200行的数据即可,而不是1-1000行的完全数据。默认的传送方式如图1所示。
从图1中可以看出,DataGrid的内建分页方法效率不高,每次请求都必须把整个查询结果发送给Web服务器,Web服务器再把数据分成相应的页面。利用DataGrid的内建的分页方法尽管是很简单的,但是,由于Web应用的无序性特征,一个用户每次从一个页面转向另外一个页面时,DataGrid对象都被销毁并重新创建,这就意味着数据库服务器每次都必须发送全部的结果集。
2、自定义分页技术
那么如何通过自定义的分页方法来实现快速处理大量数据的结果集呢?
它比DataGrid的默认分页方法更加快速有效,因为每次请求不需要把全部的数据结果都发送到Web服务器。相反,它只需要发送每个页面需要的那些数据集。自定义的分页方法只返回所要检索的那些结果集,如图2所示。
从图2中可以看到,数据库每次只需要返回所要显示的数据记录。
在ASP.NET页面中执行SQL命令的方法可以是直接执行也可以先将SQL命令封装在存储过程中,然后再页面中执行该存储过程。执行存储过程比直接执行SQL命令稍微复杂一些,但能显著提高数据库驱动的Web站点的性能。每次从ASP.NET页面直接执行SQL命令时,都需要SQL Server对其进行解析、编译和优化,而存储过程只需要进行一次解析、编译和优化。
而这里自定义的分页方法就是使用存储过程来做分页的工作,而不是由Web服务器来做。
首先,在数据库中建立一个存储过程,该存储过程接受两个输入参数,分别是要返回数据的第一条记录数和最后一条记录数。要创建一个返回指定条记录结果的存储过程,首先必须指定返回结果集的条记录数,这里用table变量(SQL Server 2000),table变量尽管是存储在内存中的,但在存储过程结束后自动释放。创建的存储过程如下:
参数@StartRow和@StopRow接收整数值,代表要返回的开始记录和结束记录,如果要在一个25条记录的页面中返回第8页,我们就可以设置@StartRow为176,@StopRow为200。
table变量@t_table中定义了一个叫rownum的整数类型的列,并指定为标识符列,它将在插入数据的时候自动增加,起到排序作用。Set RowCount语句是优化性能的关键,它会告诉SQL Server进行限制要插入的数据,如果我们要176-200条记录之间的数据,那么就可以不必插入大于200条记录的数据。最后的SQL语句通过@t_table的table变量选择rownum大于或者等于@StartRow的那些数据集,然后把它们返回到Web服务器,由Web服务器绑定到DataGrid对象。但如果浏览者请求的页数越来越大,需要向table变量填充的记录就越多,导致页面性能有所下降。因此,性能将依赖于你计算机的硬件和你要返回的记录数,但为了减轻数据库和网络传输的压力,设计合理的查询结果页数是很见效的。
然后将为DataGrid对象编写代码来使用分页技巧。DataGrid的AllowPaging、AllowCustomPaging、PageStyle属性有助于记录用户的访问状态。首先设定AllowCustomPaging为True。我们使用SQLDataReader来装载DataGrid对象。据性能测试表明:在构建列表显示数据时,使用SQLDataReader比使用DataSet要快两倍以上。
为了追求性能最佳化,设定DataGrid的EnableViewState属性为false,因为这样在每次与Web服务器打交道时就不必再在viewstate中存储内容了。
当DataGrid不在viewstate中进行保存,需要添加导航按钮来帮助用户进行导航。
那么在页面上增加两个按钮:“上一页”和“下一页”。要进入下一页,就在“下一页”按钮上增加click事件,通过自定义分页存储过程请求相应的记录。例如:如果第一页由第1条到第25条记录组成,那么要导航到第二页,我们就向存储过程的@StartRow传递参数26,向@StopRow传递参数50即可,要返回到第一页,@StartRow和@StopRow分别为1和25。
在这里使用VB.NET编写“下一页”事件:
在上面的例子中,viewstate中保存的只是@StartRow和@StopRow的信息,这比在viewstate中保存整个DataGrid对象高效的多。
结束语
以上程序是在SQL Server 2000实现的,但对于其他关系型数据库同样适用,比如ORACLE等等。列表显示信息的性能对浏览者的访问是很重要的,设计不好的列表显示会大大降低应用程序的性能,不管它的后端数据库是多么快速。使用自定义分页技术,可以避免DataGrid默认分页机制带来的缺陷,在.NET框架的强大冲击下,ASP.NET已成为新一代网站开发的主流技术,因此本文讨论的技术很具有实用价值
在创建链接和命令对象之后就要把返回的记录显示出来。DataGrid控件是ASP.NET中功能最强大也是最复杂的数据控件,可以用它来显示和格式化数据表的数据,它除了内建的数据表现和方法之外,还允许用户自己定义表现形式。分页技术为用户可管理的数据查找提供方便。
1、DataGrid内建分页技术原理
DataGrid内建分页技术很容易实现,但数据量很大时,它的方便性是以牺牲性能为代价的。如果一个用户只要求100个页面中每页显示25条记录的第8页的结果集,服务器只需要发送第175-200行的数据即可,而不是1-1000行的完全数据。默认的传送方式如图1所示。
![]() 图1 DataGrid默认传送方式 |
从图1中可以看出,DataGrid的内建分页方法效率不高,每次请求都必须把整个查询结果发送给Web服务器,Web服务器再把数据分成相应的页面。利用DataGrid的内建的分页方法尽管是很简单的,但是,由于Web应用的无序性特征,一个用户每次从一个页面转向另外一个页面时,DataGrid对象都被销毁并重新创建,这就意味着数据库服务器每次都必须发送全部的结果集。
2、自定义分页技术
那么如何通过自定义的分页方法来实现快速处理大量数据的结果集呢?
它比DataGrid的默认分页方法更加快速有效,因为每次请求不需要把全部的数据结果都发送到Web服务器。相反,它只需要发送每个页面需要的那些数据集。自定义的分页方法只返回所要检索的那些结果集,如图2所示。
![]() 图2 自定义分页的传送方式 |
从图2中可以看到,数据库每次只需要返回所要显示的数据记录。
在ASP.NET页面中执行SQL命令的方法可以是直接执行也可以先将SQL命令封装在存储过程中,然后再页面中执行该存储过程。执行存储过程比直接执行SQL命令稍微复杂一些,但能显著提高数据库驱动的Web站点的性能。每次从ASP.NET页面直接执行SQL命令时,都需要SQL Server对其进行解析、编译和优化,而存储过程只需要进行一次解析、编译和优化。
而这里自定义的分页方法就是使用存储过程来做分页的工作,而不是由Web服务器来做。
首先,在数据库中建立一个存储过程,该存储过程接受两个输入参数,分别是要返回数据的第一条记录数和最后一条记录数。要创建一个返回指定条记录结果的存储过程,首先必须指定返回结果集的条记录数,这里用table变量(SQL Server 2000),table变量尽管是存储在内存中的,但在存储过程结束后自动释放。创建的存储过程如下:
create proc InsertStudents
@Student_Last_Name as varchar(100) = null,
@StartRow as int = null,
@StopRow as int = null
AS
---- 建立有标识符列的table变量
declare @t_table table
(
[rownum] [int] IDENTITY (1, 1) Primary key NOT NULL ,
[Student_Last_Name] [varchar] (40) ,
[Student_First_Name] [varchar] (20) ,
)
---- 在返回指定的@StopRow行数之后停止处理查询
Set RowCount @StopRow
---- 插入到table变量中
insert @t_table
(
[Student_Last_Name],[Student_First_Name]
)
SELECT [Student_Last_Name],[Student_First_Name]
FROM Students
WHERE Student_Last_Name like '%' + @Student_Last_Name like '%'
ORDER BY Student_Last_Name
---- 返回到正确的结果
SELECT * FROM @t_table WHERE rownum >= @StartRow
ORDER BY rownum
GO
@Student_Last_Name as varchar(100) = null,
@StartRow as int = null,
@StopRow as int = null
AS
---- 建立有标识符列的table变量
declare @t_table table
(
[rownum] [int] IDENTITY (1, 1) Primary key NOT NULL ,
[Student_Last_Name] [varchar] (40) ,
[Student_First_Name] [varchar] (20) ,
)
---- 在返回指定的@StopRow行数之后停止处理查询
Set RowCount @StopRow
---- 插入到table变量中
insert @t_table
(
[Student_Last_Name],[Student_First_Name]
)
SELECT [Student_Last_Name],[Student_First_Name]
FROM Students
WHERE Student_Last_Name like '%' + @Student_Last_Name like '%'
ORDER BY Student_Last_Name
---- 返回到正确的结果
SELECT * FROM @t_table WHERE rownum >= @StartRow
ORDER BY rownum
GO
参数@StartRow和@StopRow接收整数值,代表要返回的开始记录和结束记录,如果要在一个25条记录的页面中返回第8页,我们就可以设置@StartRow为176,@StopRow为200。
table变量@t_table中定义了一个叫rownum的整数类型的列,并指定为标识符列,它将在插入数据的时候自动增加,起到排序作用。Set RowCount语句是优化性能的关键,它会告诉SQL Server进行限制要插入的数据,如果我们要176-200条记录之间的数据,那么就可以不必插入大于200条记录的数据。最后的SQL语句通过@t_table的table变量选择rownum大于或者等于@StartRow的那些数据集,然后把它们返回到Web服务器,由Web服务器绑定到DataGrid对象。但如果浏览者请求的页数越来越大,需要向table变量填充的记录就越多,导致页面性能有所下降。因此,性能将依赖于你计算机的硬件和你要返回的记录数,但为了减轻数据库和网络传输的压力,设计合理的查询结果页数是很见效的。
然后将为DataGrid对象编写代码来使用分页技巧。DataGrid的AllowPaging、AllowCustomPaging、PageStyle属性有助于记录用户的访问状态。首先设定AllowCustomPaging为True。我们使用SQLDataReader来装载DataGrid对象。据性能测试表明:在构建列表显示数据时,使用SQLDataReader比使用DataSet要快两倍以上。
为了追求性能最佳化,设定DataGrid的EnableViewState属性为false,因为这样在每次与Web服务器打交道时就不必再在viewstate中存储内容了。
当DataGrid不在viewstate中进行保存,需要添加导航按钮来帮助用户进行导航。
那么在页面上增加两个按钮:“上一页”和“下一页”。要进入下一页,就在“下一页”按钮上增加click事件,通过自定义分页存储过程请求相应的记录。例如:如果第一页由第1条到第25条记录组成,那么要导航到第二页,我们就向存储过程的@StartRow传递参数26,向@StopRow传递参数50即可,要返回到第一页,@StartRow和@StopRow分别为1和25。
在这里使用VB.NET编写“下一页”事件:
Private Sub ButtonNext_Click (ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ButtonNext.Click
viewstate("StartRow") = viewstate("StartRow") + dgrid.PageSize
viewstate("StopRow") = viewstate("StartRow") + dgrid.PageSize
'运行存储过程,返回SQLDataReader
dgrid.DataSource = RunSprocReturnDR (textSt_lname.Text, textSt_fname.Text, viewstate("StartRow"),viewstate("StopRow"))
dgrid.DataBind()
End Sub
ByVal e As System.EventArgs) Handles ButtonNext.Click
viewstate("StartRow") = viewstate("StartRow") + dgrid.PageSize
viewstate("StopRow") = viewstate("StartRow") + dgrid.PageSize
'运行存储过程,返回SQLDataReader
dgrid.DataSource = RunSprocReturnDR (textSt_lname.Text, textSt_fname.Text, viewstate("StartRow"),viewstate("StopRow"))
dgrid.DataBind()
End Sub
在上面的例子中,viewstate中保存的只是@StartRow和@StopRow的信息,这比在viewstate中保存整个DataGrid对象高效的多。
结束语
以上程序是在SQL Server 2000实现的,但对于其他关系型数据库同样适用,比如ORACLE等等。列表显示信息的性能对浏览者的访问是很重要的,设计不好的列表显示会大大降低应用程序的性能,不管它的后端数据库是多么快速。使用自定义分页技术,可以避免DataGrid默认分页机制带来的缺陷,在.NET框架的强大冲击下,ASP.NET已成为新一代网站开发的主流技术,因此本文讨论的技术很具有实用价值