在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
篇文章讲述了如何利用SQL Server 2005的新特性来简单高效的实现分页。对于那些暂时还没用到SQL Server2005的人们,请看在大规模数据中的高效分页方法。如果需要,这篇文章会补上这里讲到的内容。 出处:http://aspnet.4guysfromrolla.com/demos/printPage.aspx?path=/articles/031506-1.aspx 介绍 web开发中普遍会用页面来显示数据。比起整页显示一张报表或者一张数据表的数据给用户,开发者经常用到的是分页显示,每页只显示部分数据,用翻页来控制。在ASPV.NET 1.X里,DataGrid控件使翻页显示变得简单—只需要把属性AllowPaging设置为”true”,并在PageIndexChanged事件中加少量几行的代码就可以实现!ASP.NET 2.0中的控件GridView使事件也简单化了,只需要在GridView的智能面板里把“允许分页”选中,不需要一行代码就可以实现。 当然了,生活中没有任何事是容易就能做好的。你需要权衡选中一个复选框就能实现的分页方案(或者用DataGrid,写几行代码的实现方案)的性能。如果不选中分页,DataGrid和GridView使用默认分页,简单的把所有数据从头到尾地显示在一张网页上。当数据量小时,几十一百或类似的数量时,效率性能不会太明显。但是,如果你想像这样用默认的分页方法显示上千万、以至几十万的书时就不可行了。 取代默认分页的方法就是自定义分页,你要做的工作就是用代码来判断并把正确的分页数据取出,可能会费点事,但对于应付如此庞大的数据量来说,绝对值得。我在《ASP.NET Web数据控件快速开发》中讨论了如何在ASP.NET 1.X中实现自定义分页,这篇文章,我们来看在ASP.NET 2.0中如何利用SQL Server 2005的新特性 ROW_NUMBER()来实现自定义分页。(更多关于SQL SERVER的新特性说明,请看利用Microsoft SQL SERVER 2005返回列值。) 继续读下去来学习更多吧! 默认分页与自定义分页对比 在ASP.NET 2.0里GridView(或ASP.NET 1.X里的DataGrid)提供两种分页模型:默认分页与自定义分页。这两种模型在性能与易用性上提供了折中的方案。SqlDataSource控件使用默认分页(尽管你可以在自定义分页了使用它);ObjectDataSource默认使用默认分页模型,不过有个简单的配置可以让它使用自定义分页。心里要时刻记得GridView仅仅是显示数据;它才是GridView负责从数据库中检索数据的数据源控件。 使用默认分页,每次打开新页显并显示时,都要从GridView的数据源控件中获得所有数据。一旦全部的数据返回,GridView就把所有的数据全显示在页面上,于是用户看到一张页面上显示了如此多的数据。关键要理解这里,无论何时当用户访问第一页或翻到其他页时,所有的数据都会被重新加载一遍。 举个例子,比如说你在一家电子商务公司上班,你想让用户分页查看你们公司所销售的150中产品。并且,你想每页只显示10条数据。现在,当一个用户访问网页时,所有150条数据都被数据源空间返回过来。但GridView只显示第一个10条数据(产品1到产品10)。再想象一下,当这个用户翻看第二页的数据时,这会引发一个回发的事件,而且在这个时候GridView又会从数据源控件中获得所有的150条记录,但这时只需要显示第二个10条(产品11到产品20)。 缓存与SqlDataSource 更多关于SqlDataSource的数据集缓存,请看利用SqlDataSource缓存数据.
自定义分页的性能优势
像早前4Guys 的一篇文章讲述的那样,利用Microsoft SQL Server 2005获得行值中提到的, SQL Server 2005 引入了许多返回行值的关键词。特别提到关键词the ROW_NUMBER()可以返回一列递增的行数。因此,我们可以使ROW_NUMBER()写一条像下面的sql查询语句来获得某页的数据: SELECT ... 这里的@startRowIndex表示开始行的索引,@maximumRows表示每页显示的最大条数。这条语句会返回ROW_NUMBER()从开始的索引行数到加每页最大条数的行数一部分数据。 为了使表示跟具体,我们来看下下面这个例子。假设我们有一个表Employees有5000条数据(公司很不错哦!),看下面的查询语句: SELECT RowNum, EmployeeID, LastName, FirstName 返回的结果如下: RowNum EmployeeID LastName FirstName
配置ObjectDataSource支持自定义分页 正如前面提到的,一方面,SqlDataSource并没有设计成能提供自定义分页;另一方面,ObjectDataSource被设计成了能支持这个方案。ObjectDataSource被设计成能从一个object读取数据的数据源控件。这个object不管从哪、怎样取出数据,像从一个web 服务、一个数据库、一个文件系统,或一个XML文件……等等。ObjectDataSource并不关心,它就像在数据存储者和数据需要者(像一个GridView控件)之间充当了一个中介。(更多关于ObjectDataSource请看ObjectDataSource控件概述) 当把一个Web数据控件绑定到一个ObjectDataSource并设置为“允许分页”时,如果你没有具体设置ObjectDataSource来支持自定义分页,会使用默认方案来分页。要使ObjectDataSource支持自定义分页,你需要使一个object来提供以下这些方法: 1. 一个包含两个整型参数的方法。第一个整数表示检索数据开始的索引位置(起点),而第二个整数表示每页显示的最大条数。这个方法在调用时会返回我们所请求的数据,也就是从检索开始位置到往后每页显示最大条数的准确记录,而不是把所有数据记录都取出来。 2. 一个返回全部分页的数据记录数量(整数类型)的方法。(这是Web数据控件在在初始化时需要的,这样就可以显示出要分出的总页数或者是是否还需要有下一页。) 如果你要用到基础的object类型,配置ObjectDataSource来实现分页是很简单的,来看一下下面的这些ObjectDataSource的属性: 把EnablePaging设置为True 把SelectMethod设置为提供开始页和开始最大行数的参数以检索数据的方法 把StartRowIndexParameterName设置为你在SelectMethod中用到的表示检索开始位置的变量;如果你不设置这个,它默认为取startRowIndex的值 把MaximumRowsParameterName设置为你在SelectMethod用到的每页最大记录数,如果你不设置这个,它默认取maximumROws的值 把SelectCountMethod设置为返回分页的所有记录的总数的方法 就这么简单。如果你像这样配置了,那么ObjectDataSource就使用自定义分页了。当然,难点是创建能正确的取出数据的基础对象。但你一旦有了这个基础对象,要实现自定义分页也就配置一下ObjectDataSource的几个属性而已。 创建一个支持自定义分页的对象 为了使一个ObjectDataSource绑定到一个GridView,我们需要一个能灵活取得需要数据的底层对象,这个对象还能够返回需要分页的记录数。像约瑟夫校长的文章中写的那样, 《在Visual Studio 2005和中ASP.NET 2.0使用强对象类型》和布莱恩·诺伊斯的文章 《利用Visual studio 2005 数据集设计器做数据访问层》中讲述的那样,在Visual studio 2005中创建能绑定到ObjectDataSource上的对象集是一件很容易的事情。首先要定义取出数据集的存储过程(或sql查询语句),以便让那些强类型的数据集返回数据。 接下来,在本文的最后提供的,有一个包含5000条职员的范例数据库(大批量增加记录是很容易的)。这个数据库包含了2个自定义分页示例中要用到的3个存储过程: GetEmployeesSubset(@startRowIndex int, @maximumRows int) – 返回按EmployeeID排序后从@startRowIndex开始的最多@maximumRows条记录。 GetEmployeesRowCount – 返回Employees表里的记录总数。 GetEmployeesSubsetSorted(@sortExpression nvarchar(50), @startRowIndex int, @maximumRows int) – 这个存储过程返回一页经过指定条件排序的数据。也就是说能返回比如支持薪水排序后的记录。(GetEmployeesSubset只能返回按EmployeeID排序的记录。)这个扩展当你需要使用自定义分页中有自定义排序时会用到。 在这篇文章里我们不计划讲述关于自定义分页中的自定义排序,尽管在这篇文章的下载中也提供了这样的例子;可以通过《自定义分页中的数据排序》看到如何建立自定义分页并支持双向排序…… 创建完这些存储过程以后,我在我的项目里加入一个强类型的数据集文件(Employees.xsd)。然后在里面加入三个与三个存储过程相对应的方法。最后我加入了一个返回EmployeesTableAdapter对象的方法GetEmployeesSubset(startRowIndex,maximumRows)和一个可以设置到ObjectDataSource属性上的方法GetEmployeesRowCount()。(关于创建强类型数据集的详细步骤去看《在Visual Studio 2005和 ASP.NET中使用强类型数据集》和思考特·格思里的博客文章《在VS2005和ASP.NET 2.0中用强类型数据集创建数据访问层》。) 默认分页与自定义分页性能比较 在本文最后有关于默认分页与自定义分页的性能比较的数据库(包含一张5000条数据的表),我用SQL和ASP.NET找出性能的差距。(这些测试在我电脑上做是很不严谨的,因为我的电脑还同时运行着其他的程序,虽然结果不能被称做证明,但我想自定义分页的性能在比较中肯定是有优势的。) SQL查询结果
自定义分页 SqlDataSource缓存
当缓存是空的时,SqlDataSource方案消耗时间很长,因为它必须到数据库去取得所有数据,缓存在服务器。而服务器有空闲资源时才重新载入(如果只有少量的资源,缓存的数据集就会被清除出内存)并且不再载入。在数据被缓存后,虽然在性能上很接近自定义分页,但0.516秒的平均时间会随着越来越多的缓存数据而接近0.05秒。 总结 ASP.NET 1.x中的DataGrid和2.0中的GridView有两种分页方案:默认分页与自定义分页。默认分页很容易做到,但每次访问每个页面都会访问数据库并取出所有数据。而自定义分页非常高效,灵活地取出该取出的那些数据。SQL SERVER 2005由于它的新特性ROW_NUMBER()能取出行数的能力,使取出某段数据简单了。 如果你做的WEB程序现在或将来有可能让用户翻页查看庞大的数据,那么你用自定义分页是很合适的。 快乐开发! |
请发表评论