.NET TIPS

[ASP.NET]GridViewコントロールで大量のデータをページ表示するには?[2.0、3.0、3.5、C#、VB]

山田 祥寛
2009/05/14

 GridViewコントロールでページング処理を実装するのは簡単だ。「TIPS:[ASP.NET]GridViewコントロールでデータソースの内容を表示するには?」で見たように、GridViewコントロールのタスク・メニューから[ページングを有効にする]をチェックするか、またはプロパティ・ウィンドウからAllowPagingプロパティをTrueに設定すればよいだけだ*1

*1 ページングの細かな制御については、「TIPS:[ASP.NET]GridViewコントロールでページング方法をカスタマイズするには?」が詳しいので、併せてご参照いただきたい。

 もっとも、GridViewコントロールの標準的なページング機能には手軽な半面、問題もある。というのも、GridViewコントロール(正確にはSqlDataSourceコントロール)では、内部的にはグリッド表に表示するすべてのデータをいったん取得してから、1ページ分のデータだけを抽出して表示しているにすぎない。このため、データの総件数が多い場合には、データ取得のオーバーヘッドが大きくなるという欠点があるのだ。

 しかし、「TIPS:[ASP.NET]GridViewコントロールにオブジェクトをバインドするには?」(以下、前回のTIPS)で取り上げたObjectDataSourceコントロールを利用することで、1ページの表示に必要なデータだけを絞り込んで取得できるため、ページング処理のオーバーヘッドを軽減できる。本稿では、そのための具体的な方法について解説する。

 なお、本稿のサンプルは、前回のTIPSでも取り上げたObjectDataSource.aspxを基にするものとし、手順も差分のみを解説する。データアクセス・コンポーネントやObjectDataSourceコントロールの基本的な使い方については、前回のTIPSも併せて参照いただきたい。

1. データアクセス・コンポーネントにメソッドを追加する

 データアクセス・コンポーネントをページング機能に対応させるには、テーブル・アダプタに次のメソッドを定義しておく必要がある。

  • 取得するレコードの総件数を得るためのCOUNTメソッド
  • 先頭から数えてm〜n件目のデータだけを取得するSELECTメソッド

 このうち、COUNTメソッドについては、前回のTIPSで解説したTableAdapter構成ウィザードを利用することで生成できる。前回のTIPSで作成したBook.xsdファイルを開き、そのデザイナ画面上でbookTableAdapterを選択状態にしたうえで右クリックし、表示されたコンテキスト・メニューから[クエリの追加]を選択する。

[コマンドの種類を選択します]ページ([TableAdapter クエリの構成ウィザード]ダイアログ)
[SQL ステートメントを使用する]を選択。

 [コマンドの種類を選択します]ダイアログが表示されるので、[SQL ステートメントを使用する]を選択し、次へ進む。

[クエリの種類の選択]ページ([TableAdapter クエリの構成ウィザード]ダイアログ)
「単一の値を返す SELECT」を選択。

 次の[クエリの種類の選択]ページでは、単一値(件数)を返すSELECT命令を作成したいので、[単一の値を返す SELECT]を選択する。

[SQL SELECT ステートメントの指定]ページ([TableAdapter クエリの構成ウィザード]ダイアログ)
SELECT命令を確認。

 デフォルトで、bookテーブルの件数をカウントするためのSELECT命令が生成されていることを確認し、次へ進む。

[関数名の選択]ページ([TableAdapter クエリの構成ウィザード]ダイアログ)
メソッド名を入力。

 最後にメソッド名を入力して完了だ(ここでは「GetNumberOfBook」としておく)。デザイン画面に戻ったときに、ウィザードで指定したメソッドがbookTableAdapterに追加されていれば、COUNTメソッドは正しく認識されている。

テーブル・アダプタにメソッドが追加された

2. 拡張のためのコードを記述する

 もう1つ、「先頭から数えてm〜n件目のデータだけを取得するSELECTメソッド」を追加する。こちらはウィザードでは作成できず、部分クラス(Partialクラス)で定義する必要がある*2。これは次のようになる。

*2 部分クラスによるデータアクセス・コンポーネントの拡張については、「TIPS:[ASP.NET]データアクセス・コンポーネントを拡張するには?」を参照されたい。

using System;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;

namespace BookTableAdapters {
  public partial class bookTableAdapter {

    // ページングに対応したSELECTメソッドを定義((1))
    [DataObjectMethod(DataObjectMethodType.Select, false)]
    public Book.bookDataTable GetInfosForPaging(int start, int max) {

      SqlCommand comm = this.Connection.CreateCommand();

      // 現在ページの表示に必要なデータだけを取得する
      // SELECT命令を定義((2))
      comm.CommandText = String.Format(
        "SELECT * FROM (SELECT isbn, title, price, publish, published, ROW_NUMBER() OVER (ORDER BY published DESC) AS rownum FROM book) AS x WHERE x.rownum BETWEEN {0} AND {1}",
        start + 1, max + start);
      this.Adapter.SelectCommand = comm;

      // 型付きデータセットを生成
      Book ds = new Book();

      // 型付きデータテーブル(bookDataTable)に結果を流し込み
      this.Adapter.Fill(ds.book);
      return ds.book;
    }
}
Imports System.ComponentModel
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.VisualBasic

Namespace BookTableAdapters
  Partial Public Class bookTableAdapter

    ' ページングに対応したSELECTメソッドを定義((1))
    <DataObjectMethod(DataObjectMethodType.Select, False)> _
    Public Function GetInfosForPaging(ByVal start As Integer, ByVal max As Integer) As Book.bookDataTable

      Dim comm As SqlCommand = Me.Connection.CreateCommand()

      ' 現在ページの表示に必要なデータだけを取得する
      ' SELECT命令を定義((2))
      comm.CommandText = String.Format( _
        "SELECT * FROM (SELECT isbn, title, price, publish, published, ROW_NUMBER() OVER (ORDER BY published DESC) AS rownum FROM book) AS x WHERE x.rownum BETWEEN {0} AND {1}", _
        start + 1, max + start)
      Me.Adapter.SelectCommand = comm

      ' 型付きデータセットを生成
      Dim ds As New Book()

      ' 型付きデータテーブル(bookDataTable)に結果を流し込み
      Me.Adapter.Fill(ds.book)
      Return ds.book
    End Function
  End Class
End Namespace
テーブル・アダプタを拡張するための部分クラス(上:bookTableAdapter.cs、下:bookTableAdapter.vb)

 全体的なコードの流れはリスト内のコメントを参照していただくとして、ここではポイントとなる部分に注目してみよう。

(1)ページングのためのSELECTメソッドを定義する

 ページングのためのSELECTメソッドは、引数として取得開始行、取得行数(ページあたりに表示するレコード数)をint型で受け取れなければならない。メソッド名や引数名は自由に決められるが、あとから設定するObjectDataSourceコントロールのプロパティ値と対応していなければならないので、注意すること(ちなみに、引数のデータ型はint/Integer型で固定である)。

(2)行に連番を振るROW_NUMBER関数

 ここでは、ある特定範囲のレコードを取得するために、ROW_NUMBER関数を使用している。ROW_NUMBER関数はSQL Server 2005から追加された関数で、結果セットの各レコードに対して連番を振るためのものだ。具体的な構文は、次のとおりである。

ROW_NUMBER() OVER (ORDER BY ソート式)

 OVER句によりソート式を指定することで、ROW_NUMBER関数が連番を振る際のレコードの並び順を指定できる。ここでは、bookテーブルを刊行日の新しい順(published列について降順)に並べたものに対して連番を振ったうえで、そのstart + 1〜max + start番目のレコードを取り出しているわけだ。

 サブクエリを使っているので、やや複雑にも思われるかもしれないが、サブクエリの部分(SELECT isbn, title, price, publish, published, ROW_NUMBER() OVER (ORDER BY published DESC)を1つのテーブルと見なしてしまえば、ごく単純なSELECT命令であることがお分かりいただけると思う。

3. ObjectDataSourceコントロールのプロパティ値を変更する

 データアクセス・コンポーネントの準備ができたら、あとはObjectDataSourceコントロールの設定を変更するだけだ。前回のTIPSで作成済みのObjectDataSource.aspxに対して、以下の設定を追加しよう。

 なお、ページングにかかわる設定はデータソース構成ウィザードからは行えないので*3、以下のプロパティ情報をプロパティ・ウィンドウから設定する必要がある。

プロパティ名 概要 設定値
EnablePaging ページング機能を有効にするか True
SelectCountMethod レコードの全数を求めるためのメソッド名 GetNumberOfBook
SelectMethod 特定範囲のレコードだけを取得するメソッド名 GetInfosForPaging
MaximumRowsParameterName ページあたりの件数を受け取る引数の名前 max
StartRowIndexParameterName 取得開始行を受け取る引数の名前 start
ページングにかかわるObjectDataSourceコントロールの設定

*3 SelectMethodプロパティだけはウィザードから編集できるが、その場合には、引数start、maxがパラメータ情報として自動的に追加されてしまう。この場合、正しくページング処理が認識されないので、プロパティ・ウィンドウからこれらのパラメータ情報を削除しておくこと。

 以上で、ObjectDataSourceコントロールによるページングを行うための設定は完了である。これで大量のレコードに対してページングを行う場合にも、最小限のオーバーヘッドで処理を行うようになった。End of Article

利用可能バージョン:.NET Framework 2.0
利用可能バージョン:.NET Framework 3.0
利用可能バージョン:.NET Framework 3.5
カテゴリ:Webフォーム 処理対象:GridViewコントロール
使用ライブラリ:GridViewコントロール
関連TIPS:[ASP.NET]GridViewコントロールでデータソースの内容を表示するには?
関連TIPS:[ASP.NET]GridViewコントロールでページング方法をカスタマイズするには?」
関連TIPS:[ASP.NET]GridViewコントロールにオブジェクトをバインドするには?
関連TIPS:[ASP.NET]データアクセス・コンポーネントを拡張するには?

この記事と関連性の高い別の.NET TIPS
[ASP.NET]GridViewコントロールにオブジェクトをバインドするには?
[ASP.NET]データアクセス・コンポーネントを拡張するには?
[ASP.NET]GridViewコントロールでデータソースの内容を表示するには?
[ASP.NET]GridView+ObjectDataSourceコントロールでファイル一覧を作成するには?
[ASP.NET]DataGridコントロールでページ表示するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間