ASP.Net2.0 分页显示简述(附源代码)

分页显示是 ASP.Net 中常常用到的一个功能,不但能提供更好的用户体验,而且更重要的是可以大大减少网络通讯量,因为每一次页面加载只需要读取“一页”的数据量。但是 ASP.Net 2.0 中的 GridView 虽然可以通过把 AllowPaging 属性设为 True 来进行分页显示:



但如果没有定义支持分页检索数据的方法的话,这只是在显示上的分页,客户端还是一次性载入了全部数据,并没有达到减少网络负担。
要实现真正的分页显示就需要结合 ObjectDataSource 控件来“自定义”,注意 ObjectDataSource 的这几个属性:



EnablePaging
ObjectDataSource SelectCommand 是否支持分页
MaximumRowsParameterName StartRowIndexParameterName :是指 SelectCommand 所指定的方法中用于分页的两个参数名称,前者用于指定每页的记录数,后者用于指定每页开始行的索引值。
这两个值是可以根据具体调用的方法参数来更改,上图中显示的是默认值。
SelectCountMehtod :用于指定获得记录总行数的方法,要不怎么知道有多少页啊:)
 
流程:
大体上数据从数据源(如 SQL Server )到页面显示的流程如下图所示:



“自定义”就是要从底层一步步做起,以
SQL Server 2005 示例数据库 AdventureWorks 为例,现在要实现这样一个功能:根据 ShipMethodID 分页检索 Sales.SalesOrderHeader 表中的数据。
 
一、 存储过程
SQL Server 2005 中使用 ROW_NUMBER() 函数可以直接得到行数,相比较 SQL Server 2000 中子查询的方法,不仅更加简便而且大大提高了执行效率。
-- 获得当前页的表数据
CREATE PROC [Sales].[GetOrderHeadeList]
(
@shipMethodID INT,
@maximumRows INT,
@startRowIndex INT
)
AS
SET NOCOUNT ON
SELECT SalesOrderID
      ,OrderDate
      ,DueDate
      ,SubTotal
      ,TaxAmt
      ,Freight
      ,TotalDue
 FROM (SELECT ROW_NUMBER() OVER (ORDER BY OrderDate DESC) Row
              ,SalesOrderID
             ,OrderDate
              ,DueDate
              ,[Status]
              ,TaxAmt
              ,Freight
              ,TotalDue
          FROM Sales.SalesOrderHeader
         WHERE ShipMethodID=@shipMethodID) SalesOrder
 WHERE Row>@startRowIndex AND ROW<=@startRowIndex+@maximumRows
还需要一个存储过程来获得总行数:
-- 获得总记录数
CREATE PROC [Sales].[GetTotalNumberOfOrderHeader]
(
@shipMethodID INT
)
AS
SET NOCOUNT ON
SELECT COUNT(*)
 FROM Sales.SalesOrderHeader
 WHERE ShipMethodID=@shipMethodID
 
二、 数据访问层对象
调用存储过程读取数据,这里没什么特别的地方:
    public class OrderHeader:IOrderHeader
    {
        #region IOrderHeader 成员
 
        public List<OrderHeaderInfo> GetOrderHeaderList(int shipMethodID, int maximumRows, int startRowIndex)
        {
            SqlConnection conn = new SqlConnection
                (ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ConnectionString);
            SqlCommand cmd = new SqlCommand("Sales.GetOrderHeaderList", conn);
            cmd.CommandType = CommandType.StoredProcedure;
 
            cmd.Parameters.Add("@shipMethodID", SqlDbType.Int).Value = shipMethodID;
            cmd.Parameters.Add("@maximumRows", SqlDbType.Int).Value = maximumRows;
            cmd.Parameters.Add("@startRowIndex", SqlDbType.Int).Value = startRowIndex;
 
            List<OrderHeaderInfo> list=new List<OrderHeaderInfo>();
 
            conn.Open();
            SqlDataReader dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                list.Add(new OrderHeaderInfo(dr.GetInt32(0), dr.GetDateTime(1), dr.GetDateTime(2),
                    dr.GetDecimal(3), dr.GetDecimal(4), dr.GetDecimal(5), dr.GetDecimal(6)));
            }
            dr.Close();
            conn.Close();
 
            return list;
        }
 
        public int GetTotalNumberOfOrderHeader(int shipMethodID)
        {
            SqlConnection conn = new SqlConnection
                (ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ConnectionString);
            SqlCommand cmd = new SqlCommand("Sales.GetTotalNumberOfOrderHeader", conn);
            cmd.CommandType = CommandType.StoredProcedure;
 
            cmd.Parameters.Add("@shipMethodID", SqlDbType.Int).Value = shipMethodID;
 
            conn.Open();
            int result = (int)cmd.ExecuteScalar();
            conn.Close();
 
            return result;
        }
 
        #endregion
}
三、 业务逻辑层对象
通过工厂方法获得数据访问层实例,调用读取方法:
    public class OrderHeader
    {
        private IOrderHeader orderHeader = DataAccess.CreateOrderHeader();
 
        public List<OrderHeaderInfo> GetOrderHeaderList(int shipMethodID, int maximumRows, int startRowIndex)
        {
            return orderHeader.GetOrderHeaderList(shipMethodID, maximumRows, startRowIndex);
        }
 
        public int GetTotalNumberOfOrderHeader(int shipMethodID, int maximumRows, int startRowIndex)
        {
            return orderHeader.GetTotalNumberOfOrderHeader(shipMethodID);
        }
}
注意GetTotalNumberOfOrderHeader这个方法,即ObjectDataSource控件的SelectCountMethod要指定的值,该值为方法名称且不能指定参数,所以该方法的参数应与SelectCommand所指定的方法参数相一致,否则运行时会抛出异常。
 
四、 表示层(这里指ASP.Net页面)
GridView 的设置很简单,最基本的,把 AllowPaging 设为 True 即可:



ObjectDataSource
控件除了设置 SelectMothod 方法外,特别注意对开头所说的四个属性的设置:







EnablePaging
设为 True ,指定 SelectCountMethod 方法。
 
 
运行结果



使用断点调试,会发现每次只从数据库读取
10 条记录,如果不使用自定义分页,那么每次需读取近万条数据!大大节省了每一次的通讯量。

源代码下载,包含生成存储过程的T-SQL,注意修改一下web.config中的连接字符串值,文件夹Web是网站项目,其他为类库项目,新建解决方案添加一下:
PagingData.rar

原创文章,希望对大家有所帮助,不当之处请及时指正:)
 
数据访问相关教程,很多人推荐过了,还是值得在推荐一下:
英文不是很难,图文并茂,还有 VB C# 源代码
<script type=text/javascript> // </script>
Feedback
# re: ASP.Net2.0 分页显示简述(附源代码)  回复  更多评论   
2007-05-06 10:19 by wzsst
用了数据库分页,GridView的排序功能还能不能用?
# re: ASP.Net2.0 分页显示简述(附源代码)  回复  更多评论   
2007-05-06 11:19 by 徐鸿翼
只有数据源支持IEnumerable接口才可以使用GridView的排序功能如DataView、DataTable和DataSet。但即使把读取到的数据转换到以上三种类型,排序也仅仅是针对当前页的数据。
 
可以通过增加一个排序参数来实现,修改一下存储过程:
CREATE PROC [Sales].[GetOrderHeaderList]
(
@shipMethodID INT,
@sortField NVARCHAR(4000),
@maximumRows INT,
@startRowIndex INT
)
AS
SET NOCOUNT ON
SELECT SalesOrderID
      ,OrderDate
      ,DueDate
      ,SubTotal
      ,TaxAmt
      ,Freight
      ,TotalDue
 FROM (SELECT ROW_NUMBER()
               OVER (ORDER BY CASE @sortField
                      WHEN 'SubTotal' THEN SubTotal
                      WHEN 'TaxAmt'   THEN TaxAmt
                      WHEN 'Freight' THEN Freight
                      WHEN 'TotalDue' THEN TotalDue
                       END) Row
              ,SalesOrderID
              ,OrderDate
              ,DueDate
              ,SubTotal
              ,TaxAmt
              ,Freight
              ,TotalDue
          FROM Sales.SalesOrderHeader
         WHERE ShipMethodID=@shipMethodID)SalesOrder
 WHERE Row>@startRowIndex AND ROW<=@startRowIndex+@maximumRows
GridView Sorting 事件中传入参数即可
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值