The wind call my name

用知识和思考来丈量世界
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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

Posted on 2007-05-04 21:13  徐鸿翼  阅读(2500)  评论(2编辑  收藏  举报

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



但如果没有定义支持分页检索数据的方法的话,这只是在显示上的分页,客户端还是一次性载入了全部数据,并没有达到减少网络负担。

要实现真正的分页显示就需要结合ObjectDataSource控件来“自定义”,注意ObjectDataSource的这几个属性:



EnablePaging
ObjectDataSourceSelectCommand是否支持分页

MaximumRowsParameterNameStartRowIndexParameterName:是指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


原创文章,希望对大家有所帮助,不当之处请及时指正:)

 

数据访问相关教程,很多人推荐过了,还是值得在推荐一下:

http://www.asp.net/Learn/DataAccess/

英文不是很难,图文并茂,还有VBC#源代码