分頁顯示是 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
原創文章,希望對大家有所幫助,不當之處請及時指正:) 資料通路相關教程,很多人推薦過了,還是值得在推薦一下: http://www.asp.net/Learn/DataAccess/ 英文不是很難,圖文并茂,還有 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 事件中傳入參數即可