Uncategorized

[IT Pro 道場補足] 大量データを GridView で処理する

IT Pro 道場 (東京) 補足

WCF のワークフローサービスをはじめとし、間にビジネスロジック処理部分に相当するサービスを介して Web の UI 上でグリッド表示をおこなうには、プログラムによるデータの取得が必要なため、「オブジェクトデータソース」というものを使用します。
オブジェクトデータソースでは、データを取得するメソッド(およびそのメソッドを提供するクラス)を指定してこれを利用して処理されますが、ここでは、その使い方の詳細は記載しません。基本的な手順については、こちらのStep7 などを参照してください。

ここでは、このオブジェクトデータソースを使って、デモでお見せしたような 10 万件、100 万件といった大量データを扱う方法について記載します。

オブジェクトデータソースでは、たとえページング処理をおこなって件数を絞ったとしても、毎回、全件検索をおこないます。(というか、正確な書き方をすると、そうした関数を標準で利用するようになっています。) この理由は、たとえページング処理をおこなっていても、件数が何件あるかわからなければ、ページングで何ページ目までを表示してよいかわからないためです。(IT Pro 的には、SQL プロファイラーなどを使って毎回検索に走っているのが確認 (トレース) できます。)

さて、たとえ表示するデータ数が 5, 6 件であっても、ビジネスロジック層 (WCF サービスなどのアプリケーションサーバ側) で全件検索して受け渡すわけですから、ビジネスロジックを実装しているアプリケーションサーバーとUIを実装しているWebサーバー間を 10 万件のデータが流れることになります。これでは、大規模なシステムには対応できません。では、このオブジェクトデータソースの動きを制御できないのでしょうか?

実は可能です。

デモでは何も説明せずに直してしまいましたが(すみませんでした、時間の関係で割愛しました)、おおまかに概念を記載すると、オブジェクトデータソースにおける「データを取得するメソッド」を「データ件数を取得するメソッド」と「表示データのみを取得するメソッド」にわけて実装する、といった感じに実装方法を変えます。
では、その手順を以下に記載します。

  1. まず、「・・・件目から・・・件を取得する」ことができるような SQL を作成しておきましょう。
    以下は 1 つの例ですが、@StartIndex に開始行、@MaxCount に抽出する件数を指定した場合のサンプルを示しておきます。
    実際にはこれをストアドプロシジャなどとして作成しておくと良いでしょう。2 以降のサンプルでは、GetMaterials という WCF サービス (アプリケーションサーバ上のサービス) のメソッドの中でこの処理をおこなっているものと仮定して進めます。

    select type, name from
    (select top (@MaxCount + @StartIndex) row_number() over (order by type) as rownum, type, name from
    (select type, name from materials) innertable1) innertable2
    where rownum > @StartIndex

    ※ 尚、この検索では、@MaxCount + @StartIndex 件を対象に検索し、そこから rownum > @StartIndex に絞っていますが、本来は、最初に @MaxCount 件に絞っておくと内部動作的にもっと速くなることでしょう (SQL Server の場合はどうしてもこのようになってしまいますが、もっと良いアイデアをお持ちの方は是非このブログにコメントください)

  2. SQL の準備ができたら、Web UI (ASP.NET) 側の GridViewの設定で、ページングを有効にしておきます。(これは、ページングを使う場合にはいつもやられることです。)
  3. つぎに、オブジェクトデータソースのプロパティを表示し、以下の図にあるように、EnablePaging を true に設定します。
    これにより、上述のように、「データ件数を取得するメソッド」(SelectCountMethod)と「表示データのみを取得するメソッド」(SelectMethod)にわけて実装できますので、それぞれに存在するメソッドを入力します。(TypeName には、そのメソッドが属しているクラスを記載します。)
    今回は、それぞれを GetEntryCount と GetEntry としておきましょう。

  4. それぞれのメソッドを以下の通り実装します。
    GetEntry では、EnablePaging が false のときと異なり、引数として、表示する件数と開始行の番号を受け取るります。また、件数を取得する関数のほうは、毎回検索しなくて良いように、初回ロード時にセッションなどに入れておき、これをずっと使用するようにしましょう。(GetMaterials では、WCF サービス側で、上述の SQL を使ってデータ取得をおこなっているものとします。)

    public InformationServiceReference.MaterialData[] GetEntry(int maximumRows, int startRowIndex)
    {
        InformationServiceReference.InformationServiceClient cl = new InformationServiceReference.InformationServiceClient();
        InformationServiceReference.MaterialData[] retVal = cl.GetMaterials(startRowIndex, maximumRows);
        cl.Close();
        return retVal;
    }

    public int GetEntryCount()
    {
        return (int)HttpContext.Current.Session[“orderweb_material_count”];
    }

  5. したがって、初回ロード時には、以下のように件数を検索し、セッションに入れておきましょう。(今回、以下のサンプルでは、道場のときのように、WCF につないで検索するものとして記載しています。)

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            InformationServiceReference.InformationServiceClient cl = new WebApplication1.InformationServiceReference.InformationServiceClient();
            Session[“orderweb_material_count”] = cl.GetMaterialCount();
        }
    }

Advertisements

Categories: Uncategorized

Tagged as:

2 replies »

  1. こんにちは。 IT Pro 道場「アプリケーションプラットフォーム編」にご参加いただき、ありがとうございました。 と共に、いきなりアプリが動かず、以降のデモのいっさいをお見せすることができなくなってしまい申し訳ございませんでした。

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s