摘要:本文针对web数据库记录的显示问题,用实例讨论了在asp.net框架下使用datagrid控件对数据库记录的一种自定义分页显示。
关键词:web数据库;asp.net;datagrid;分页
引言
在用户进行数据查询时通常有这样的情况,一个数据库查询将返回太多的行,一致不能在一页中显示。如果用户正在使用一个慢的链接,发送特别大的数据结果可能要花很长的时间。一旦获得了数据,用户可能发现它不包含正确的内容,或者查询范围太大,没有容易的办法检查完所有的结果来找到重要的信息。因此,对查询结果分页显示将为用户可管理的数据查询提供极大的方便。分页显示是一种非常常见的浏览和显示大量数据的方法,属于web编程中最常处理的事件之一,现在网站基本上都提供了分页显示信息的功能,但大部分还是基于asp的,而.net平台框架是针对各种各样的web应用设计的,因此本文讨论了一种在asp.net框架下实现查询记录自定义分页显示的技术。
asp.net
.net是通过平台独立的数据描述方法(通过xml)和通用的访问媒介internet来简化用户访问和存储信息的过程。
asp.net是microsoft.net框架的核心元素,是一项基于服务器的强大技术,利用它,可以为www站点或企业内部网创建动态可以交互的html页面。asp.net 完全基于模块和组件,具有很好的可扩展性和可定制性。它主要包括webform和webservice两种编程模式。前者为用户提供功能强大、外观丰富的基于表单(form)的可编程web页面;后者通过对http、xml、soap、wsdl等internet标准的支持提供在异构网络环境下获取远程服务、链接远程设备、交互远程应用的编程界面。
通过ado.net链接、操纵数据源
在microsoft公司推出开放式数据库互连(odbc)应用程序编程接口(api)以来,出现了各种各样的数据库访问技术,而直到ado.net出现,api才能实时地给出处理效果。ado.net是asp.net应用程序用来与数据库进行通信的技术,使你可以同关系数据库和其他数据源进行交互。断开的访问是ado.net最重要的特性,是对ado最大的改变。ado.net创建一个到数据库的链接,用从数据库中提取的信息副本填充数据集。如果改变了数据集(dataset)中的信息,数据库里相应表格中的信息不会改变。需要时,可以把dataset连回最初的数据源并应用所有的改变。
ado.net主要依赖以下核心对象的功能。它们分为两个组:一组对象用来存放和管理数据(例如:datatable,datarow和datarelation),另一组对象用来链接到某个特定的数据源(例如:connections,commands和datareader类)
在大多数的情况下,需要的数据是在某个数据源(例如:某个关系数据库)中。要想对这些数据进行访问、提取并将其插入到适当的数据对象中,就必须使用数据源对象。使用数据源对象的目的是创建一个链接并把相关信息移入某个dataset或datareader中。一种最简单的数据库访问方法是:利用command对象直接进入数据源并通过datareader检索只读数据行。另一种选择:把数据放入某个断开链接的dataset,从而在更长的时间段操作。
用datagrid控件分页显示记录
在创建链接和命令对象之后就要把返回的记录显示出来。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
参数@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
在上面的例子中,viewstate中保存的只是@startrow和@stoprow的信息,这比在viewstate中保存整个datagrid对象高效的多。
结束语
以上程序是在sql server 2000实现的,但对于其他关系型数据库同样适用,比如oracle等等。列表显示信息的性能对浏览者的访问是很重要的,设计不好的列表显示会大大降低应用程序的性能,不管它的后端数据库是多么快速。使用自定义分页技术,可以避免datagrid默认分页机制带来的缺陷,在.net框架的强大冲击下,asp.net已成为新一代网站开发的主流技术,因此本文讨论的技术很具有实用价值。
