ASP.NET 2.0数据教程之二十六:排序自定义分页数据2010-08-09 翻译:cnblogs LoveCherry返回“”导言和默认翻页方式相比,自定义分页能提高几个数量级的效率。当 我们的需要对大量数据分页的时候就需要考虑自定义分页,然而实现自定义分页 相比默认分页需要做更多工作。对于排序自定义分页数据也是这样,在本教程中 我们就会扩展前面的例子来实现自定义分页数据的排序。注意:既然本教 程是基于前一个的,因此我们需要把前面教程示例页面EfficientPaging.aspx的 <asp:Content>元素中的代码复制到本教程SortParameter.aspx示例页面中 。关于如何进行这样的复制操作请参看为删除数据添加客户端确认Step 1: 回顾自定义分页技术要实现自定义分页,我们需要使用一些方法根据 开始行索引和最大行参数返回一个记录的子集。在前面的教程中,我们看了如何 使用微软SQL SERVER 2005的ROW_NUMBER()来实现。简而言之,ROW_NUMBER()为每 一个查询返回的行分配一个行号。下面这个查询演示了如何使用这个技术按照 ProductName排序获取的11至20的产品数据。
| SQL |
1 2 3 4 5 | SELECT ProductID, ProductName, ... FROM (SELECT ProductID, ProductName, ..., ROW_NUMBER() OVER (ORDER BY ProductName) AS RowRank FROM Products) AS ProductsWithRowNumbers WHERE RowRank > 10 AND RowRank <= 20 |
对 于按照一种固定的排序规则进行分页,上述技术就能满足了(比如按照 ProductName排序),但是如果我们希望获取按照不同的排序表达式排序后的记录 ,理想地,我们应该在OVER子句中使用参数重写上述查询,代码如下:
| SQL |
1 2 3 4 5 | SELECT ProductID, ProductName, ... FROM (SELECT ProductID, ProductName, ..., ROW_NUMBER() OVER (ORDER BY @sortExpression) AS RowRank FROM Products) AS ProductsWithRowNumbers WHERE RowRank > 10 AND RowRank <= 20 |
可惜,ORDER BY子句中不能使用参数。而我们只能创建存储过程来接受 @sortExpression输入参数,使用如下任意一种方法:为所有的排序表达 式硬编码查询,使用IF/ELSE T-SQL语句来决定执行哪个查询使用CASE语 句来根据输入参数@sortExpression实现动态ORDER BY表达式,详细请看The Power of SQL CASE Statements中的Used to Dynamically Sort Query Results 部分。使用字符串来保存查询语句然后使用sp_executesql系统存储过程 来动态执行查询上述每一种实现方法都有各自的缺点。第一个方案和其 余两个相比可维护性比较差,因为它需要为每一个可能的查新表达式创建一句查 询。因此,如果你又在GridView中加入了一个允许排序的字段,还需要去修改存 储过程。对于第二个方案如果我们的数据库列不是字符串类型的话,排序就会引 发一定的效率问题,而且可维护性和第一种一个一样也不是很好。至于最后一个 动态组合SQL语句的方案,如果你允许用户自己输入参数并传入存储过程的话则可 能带来SQL注入攻击的危害。虽然没有一种方案是完美的,但是我认识第 三种是这三个方案中最佳的。因为它是使用动态SQL语句的,所以灵活性比前两者 都好。而且,只有当攻击者能随意把参数传入存储过程才能进行SQL注入攻击。既 然DAL使用参数化查询,ADO.NET会防止这些恶意参数传入数据库,也就是说只有 当攻击者人直接执行存储过程的时候才会有SQL注入的隐患。要实现这个 功能,让我们在Northwind数据库中新建称作GetProductsPagedAndSorted的一个 存储过程。这个存储过程接受三个参数:@sortExpression,nvarchar(100)类型 的输入参数,用来指定排序方式,它会直接拼接在ORDER BY子句后面。 @startRowIndex 和 @maximumRows都是整数输入参数,和前面教程中的一样。你 可以参考下面的脚本建立GetProductsPagedAndSorted存储过程: