QA@IT

ASP.NETで、GridViewの件数制限

7532 PV

ASP.NET(2010)でデータ量の多いデータをグリッドビューに表示しようとしているのですが
DataSourceに設定したデータセットは
10000件だけど、実際に表示されるのは2000件まで
という風にする方法はないでしょうか

ページ表示にしようと思ったら、
「それはだめ。昔通りにして」と言われてしまったので・・・

GdidViewとは別のところにラベルを作って(10000件中/2000件まで表示」というような表示も必要なのですが
こうなってしまうと、Select文を件数を取得するSQLと、
実際にデータを取得するときにSELECT TOP(2000) cola,colb・・・
とわけるように
するしかないのでしょうか

回答

「それはだめ。昔通りにして」と言われてしまったので・・・

「昔通り」とは具体的にどういう意味なのですか?

質問者さんはサーバーで起こっていることとクライアントで起こっていることの違いは認識されているでしょうか?

つまり・・・

DataSourceに設定したデータセットは
10000件だけど、実際に表示されるのは2000件まで

というところで、「DataSourceに設定したデータセットは 10000件」がサーバー側で起こっていることで、「実際に表示されるのは2000件」というのがクライアントで起こっていることです。

そして、サーバーは 2000 件表示するための html ソースをクライアントに送信したあと、直ちに 10000 件のデータを保持している DataSet をサーバーのメモリから消去してしまいます。

・・・ということです。

多分「昔通り」にしてと言った人の思惑は、クライアントが次の 2000 件を見る場合に、DB に再度要求をかけるのではなく、DataSet からデータを得るといったことだと思います。

しかし、何もしなければ、クライアントがサーバーに次の 2000 件の要求を出す時には、前回の要求時に作成した DataSet はサーバーのメモリから消去されていて影も形もありません。

従って、上で言う「昔通り」にするためには、サーバー側で DataSet を何らかの方法で保持する必要があります。

サーバーで DataSet を保持するために現実的なのは、サーバーのキャッシュを使うことです。(Session や ViewState は全く現実的ではないと思います)

ASP.NET には、「SQL キャッシュ依存関係」という、ASP.NET のキャッシュと SQL Server DB のテーブルやレコードとの間に依存関係を持たせ、当該テーブル/レコードが変更されたら ASP.NET のキャッシュを削除し、次のリクエストでは新しいデータを DB から取得してユーザーに提供するとともに、新しいデータをキャッシュできるようにするための機能があります。。

それを利用することを検討してはいかがですか。詳しくは以下のページを見てください。

SQL キャッシュ依存関係
http://surferonwww.info/BlogEngine/post/2011/03/28/SQL-Cache-Dependency.aspx

編集 履歴 (2)
  • 「普」通ではなくて「昔」通りですね。ページ切り替えのない既存のアプリと同じにしてとかそういう意味なんじゃないかと思いますよ。 -
  • 訂正しました。 普通どおり ⇒ 昔通り -
  • 遅くなってしまい申し訳ありません。それと、ありがとうございます。
    まだちょっとの見込めていない部分があるのですが、サンプルを作る時間がもらえたので試してみます
    -
  • もう一度書きますが「昔通り」とは具体的にどういう意味なのですか?
    回答者の質問を無視しないできちんと答えていただければと思います。
    -

やり方はいろいろあるとは思いますが、

たとえばDataSet dsがあり、ds.Tables[0]に表示対象のテーブルが入っているとします。

現在以下の様にバインドしているとして話を進めます。

dataGrid1.DataSource = ds;
dataGrid1.DataBind();

pagerを使う

pagerを使いつつ、ページのナビゲート部分を非表示にすれば1ページ目だけ表示され、しかもページ替えの部分が非表示なので目的を果たせるのではないかと思います。

dataGrid1.DataSource = ds;
dataGrid1.AllowPaging = true;
dataGrid1.PageSize = 2000;
dataGrid1.PagerStyle.Visible = false;
dataGrid1.DataBind();

表示用DataTableを作成する

以下の様に件数をしぼったDataTableを後から作成してそれをバインドする手もあります。
DataTableの作成方法はいろいろあるとは思いますが、例をあげておきます。
この方法ですとDataTableが新たに作成されますので、状況によってはそれはデメリットとなる場合もあります。

dataGrid1.DataSource = ds.Tables[0].AsEnumerable().Take(2000).CopyToDataTable();
dataGrid1.DataBind();

カウントを別途取得する

表示部分以降が使われることが無いのであれば素直に、
SQLで必要なレコードだけを取得し、同じくSQLで別途カウントを取得する方が良いでしょう。


DataTableに全件取得している場合、件数が増えるとDataTableが肥大化していきデータ取得時に時間がかかるだけでなくメモリも圧迫していきます。セッションごとにDataTableを取得していれば、単純には同時に利用しているユーザー分無駄に確保される領域が増えるという事です。2001件目以降が使われる事が無いのであれば、カウントを別途とる方が良いかと思います。

この辺りはトレードオフですので環境に合わせて使い分けられるといいと思います。

編集 履歴 (0)
  • ありがとうございます。Pagerは真っ先に拒否されてしまいました。カウントをおとなしく再発行するか、 SurferOnWww さんに教えていただいた方法と検討してみます。 -
  • ページ切り替え部分は非表示で、ページ切り替えはさせないんですがそれでも拒否されるんです? -
ウォッチ

この質問への回答やコメントをメールでお知らせします。