資料分頁的方式很多種,本文將介紹如何使用 DBDataAdapter.Fill 方法來做資料分頁。
要做資料分頁的方法有很多種,您可以在 DBMS 端(例如 SQL Server)或是透過具有分頁功能的控制項(例如 GridView),本文將以 SqlDataAdapter 的 Fill 方法為例,介紹其中一個多載方法來進行資料分頁。
下圖為本文所示範的頁面 Layout ,其中使用一個沒有分頁功能的 DataList 控制項,並提供使用者可以自行輸入 PageSize 的 TextBox ,用以決定每頁所要呈現的資料筆數,Bind Button 為用來根據 Page Size 來顯示資料,Previous Button 用來切換至上一頁,Next Button 用來切換至下一頁。
程式碼如下:
1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DataAdapterDemo.aspx.cs" Inherits="MSDNForumsDemo.DataAdapterDemo" %>
2:
3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4:
5: <html xmlns="http://www.w3.org/1999/xhtml">
6: <head runat="server">
7: <title></title>
8: </head>
9: <body>
10: <form id="form1" runat="server">
11: <div>
12: <asp:DataList ID="DataList1" runat="server" GridLines="Horizontal">
13: <ItemTemplate>
14: RegionID:<asp:Label ID="lblRegionID" runat="server" Text='<%# Eval("RegionID") %>'></asp:Label>
15: <br />
16: RegionDesc:<asp:Label ID="lblRegionDesc" runat="server"
17: Text='<%# Eval("RegionDescription") %>'></asp:Label>
18: </ItemTemplate>
19: </asp:DataList>
20: <br />
21: <asp:Label ID="lblPageSize" runat="server" Text="Page Size:"></asp:Label>
22: <asp:TextBox ID="txtPageSize" runat="server"></asp:TextBox>
23: <asp:Button ID="btnBind" runat="server" onclick="btnBind_Click" Text="Bind" />
24: <asp:Button ID="btnPrevious" runat="server" Text="Previous" Enabled="False"
25: onclick="btnPrevious_Click" />
26: <asp:Button ID="btnNext" runat="server" Text="Next" Enabled="False"
27: onclick="btnNext_Click" />
28: </div>
29: </form>
30: </body>
31: </html>
接著以下列程式碼來進行分頁,重點在於第 64 列的 Fill 方法。
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5: using System.Web.UI;
6: using System.Web.UI.WebControls;
7: using System.Data.SqlClient;
8: using System.Data;
9:
10: namespace MSDNForumsDemo
11: {
12: public partial class DataAdapterDemo : System.Web.UI.Page
13: {
14: int pageIndex = 0; //目前頁碼
15: int pageSize = 0; //每頁筆數
16:
17: protected void Page_Load(object sender, EventArgs e)
18: {
19: if (ViewState["pageIndex"] != null)
20: int.TryParse(ViewState["pageIndex"].ToString(), out pageIndex);
21:
22: int.TryParse(txtPageSize.Text, out pageSize);
23: }
24:
25: protected void btnBind_Click(object sender, EventArgs e)
26: {
27: pageIndex = 0;
28: DataListBind();
29: }
30:
31: private void DataListBind()
32: {
33: //將目前頁碼儲存至 ViewState 防止 PostBack 後不曉得目前頁碼
34: if (ViewState["pageIndex"] == null)
35: ViewState.Add("pageIndex", pageIndex);
36: else
37: ViewState["pageIndex"] = pageIndex;
38:
39: DataSet ds = GetPagingDataSet();
40: DataList1.DataSource = ds;
41: DataList1.DataBind();
42:
43: //若目前頁碼為第0頁,停用回上一頁按鈕
44: btnPrevious.Enabled = !(pageIndex == 0);
45: //若取得的資料筆數小於每頁筆數,表示為最後一頁,停用下一頁按鈕
46: btnNext.Enabled = (ds.Tables[0].Rows.Count == pageSize);
47: }
48:
49: private DataSet GetPagingDataSet()
50: {
51: DataSet ds = new DataSet();
52: if (pageSize == 0) return null;
53:
54: SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
55: builder.DataSource = ".";
56: builder.InitialCatalog = "Northwind";
57: builder.IntegratedSecurity = true;
58:
59: using (SqlConnection con = new SqlConnection(builder.ToString()))
60: {
61: if (con.State != ConnectionState.Open) con.Open();
62: using (SqlDataAdapter adapter = new SqlDataAdapter("select * from region", con))
63: {
64: adapter.Fill(ds, pageIndex * pageSize, pageSize, "Region");
65: }
66: }
67:
68: return ds;
69: }
70:
71: protected void btnPrevious_Click(object sender, EventArgs e)
72: {
73: if (pageIndex > 0) pageIndex -= 1;
74: DataListBind();
75: }
76:
77: protected void btnNext_Click(object sender, EventArgs e)
78: {
79: pageIndex += 1;
80: DataListBind();
81: }
82: }
83: }
利用 SQL Server Profiler 去錄製執行結果(如下圖),發現利用這種方式進行分頁,會在實際上資料還是會一次抓下來,只是在 Fill 到 DataSet 時只填入程式中所設定的範圍。
【結論】
分頁的做法很多種,在 DBMS 端、使用控制項分頁功能,或是本文利用 DBDataAdapter 的 Fill 方法,就看實務上的狀況來選擇適合的分頁方法。
【參考資料】