如何使用 DBDataAdapter.Fill 方法來做資料分頁

資料分頁的方式很多種,本文將介紹如何使用 DBDataAdapter.Fill 方法來做資料分頁。

要做資料分頁的方法有很多種,您可以在 DBMS 端(例如 SQL Server)或是透過具有分頁功能的控制項(例如 GridView),本文將以 SqlDataAdapter 的 Fill 方法為例,介紹其中一個多載方法來進行資料分頁。

下圖為本文所示範的頁面 Layout ,其中使用一個沒有分頁功能的 DataList 控制項,並提供使用者可以自行輸入 PageSize 的 TextBox ,用以決定每頁所要呈現的資料筆數,Bind Button 為用來根據 Page Size 來顯示資料,Previous Button 用來切換至上一頁,Next Button 用來切換至下一頁。

 

image

 

程式碼如下:

 

   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 時只填入程式中所設定的範圍。

 

image

 

【結論】

分頁的做法很多種,在 DBMS 端、使用控制項分頁功能,或是本文利用 DBDataAdapter 的 Fill 方法,就看實務上的狀況來選擇適合的分頁方法。

 

【參考資料】