C# Programming

ImageObjectDataSource

開発環境: Visual Studio 2005

1.目次

1.目次
2.目的
3.参考書
4.ObjectDataSource
4.1 全国または県別で選択的出力の例

2.目的

ObjectDataSourceに関してのメモです。

3.参考書

  1. @IT 第10章 3階層型自動データバインド

4.ObjectDataSource

ウィザードベースで作れるASP.NET アプリケーションの限界(2階層型自動データバインドの限界)については、参考書(1)がわかりやすい。これによると、次のような場合にウィザードベースだと対応できない。

  • パラメータ化できない可変値を持つクエリ 
    • TOP句はパラメータ化できないため、このクエリはSqlDataSourceオブジェクト上に定義できない。
    • 例:SELECT TOP @top * FROM authors
  • 条件に応じて動的に変化するWHERE句を持つクエリ
    • 指定された検索条件を基に、動的にWHERE句を組み立てるような業務
    • 例:ドロップダウンで、全国または県別で選択的に出力

このような場合に効果を発揮するのが ObjectDataSourceで、3階層型自動データバインドを容易に実現するためのメカニズムを提供してくれる。

4.1 全国または県別で選択的出力の例

次のような州ごとのドロップダウン選択は、簡単にできる。

Image

でも、ここでドロップダウンに”ALL”を入れようと思うと、WHERE がいらない SELECT文になるので、条件判断がはいることになり、単純な2層ではうまくいかなくなる。

 

4.1 SELECT TOP Xの例

そこで、ObjectDataSource を使って、対応してみる。

Step1

SQLDataSource の場合は、データベースからデータ型を取得してきてくれるのでとても楽だが、ObjectDataSourceは XML データベーススキーマ(XML schema definition)ファイルを作成する必要がある。まずは、次のようにXML データベーススキーマ(XML schema definition)ファイルを作成する。ソリューション エクスプローラから[新しい項目の追加]→[データセット] を選択する。

Image

ファイル名をわかりやすく変更して、追加ボタンを押す。ここでは、DataSetStates.xsdとした。

Image

Step 2

次に、この DataSetStates.xsd をダブルクリックして、デザイナで開く。するとつぎのように TableAdapter 構成ウィザードが立ち上がり、ObjectDataSource 上にTableAdapterをつくようにガイドしてくれる。

Image

接続文字列は、SQL Server 2005 のサンプルデータベースの AdventureWorks を使用する。次へ。

コマンドは、従業員を取得できるビューがあり、SQL文で一発でデータを取得できるので、一番上の SQL ステートメントを使用するを選択する。

Image

すると、SQL ステートメントの入力ダイアログが立ち上がるので、

Image

クエリビルダを起動して、ここではビューの vEmployee を追加する。

Image

クエリの実行で、次のようにクエリが成功すればOK。

Image

次に生成するメソッドの選択ダイアログが表示される。ここでは、デフォルトのままにして、Fill, GetData メソッドを生成するようにする。

Image

Image

これで、次のように DataSetSates.xsd として、テーブル部分とTableAdapter 部分の定義が出来上がる。この時点では、あくまで定義部分が出来上がったに過ぎない。

注意: この時点で、列はすべて文字列型で生成されてしまいます。この例では、EmployeeIDは整数型なので、プロパティを変更してあげる必要があります。

Image

Step 3

次に、AllState.aspx という新しいファイルで、コントロールを次のように追加する。

Image

GridViewのタスクから、データソースの構成選択して、

Image

オブジェクトデータソースを選択する。次に、ビジネスオブジェクトの選択を聞いてくるので、先ほど作成したvEmployeeTableAdapter を選択する。

Image

次に、データメソッドの定義を聞いている。ここでは、GetDataしか定義していないので、SELECTのメソッドしか表示されないが、完了ボタンを押して、終了する。

Image

ここまでで、SQL データソースをベースに作ったものとほぼ同等の機能ができる。

Image

ただし、ここでは SELECT にパラメータを渡していないので、ドロップダウンで別の州を選択しても何も起こらない。

実は、この裏側で、ツールによってかなりで大きなコードが自動生成されるコードがある。

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\websitetest1\???\???\Sources_App_Code

構造的に簡単にするため、関係の少ない部分をカットすると、次のようになる。


public partial class DataSetStates : System.Data.DataSet
   ...

namespace DataSetStatesTableAdapters
{
    public partial class vEmployeeTableAdapter : System.ComponentModel.Component
    {
        public virtual int Fill(DataSetStates.vEmployeeDataTable dataTable)
        {
            this.Adapter.SelectCommand = this.CommandCollection[0];
            if ((this.ClearBeforeFill == true))
            {
                dataTable.Clear();
            }
            int returnValue = this.Adapter.Fill(dataTable);
            return returnValue;
        }

        public virtual DataSetStates.vEmployeeDataTable GetData()
        {
            this.Adapter.SelectCommand = this.CommandCollection[0];
            DataSetStates.vEmployeeDataTable dataTable = new DataSetStates.vEmployeeDataTable();
            this.Adapter.Fill(dataTable);
            return dataTable;
        }
    }
}

ここで、vEmployeeTableAdapter は、DataSet から継承したパーシャルクラスで、Fill, GetData を実装しています。このvEmployeeTableAdapter クラスを、partial定義により機能拡張することができます。そこで、partial class vEmployeeTableAdapter で、 メソッドを追加して ALL が正しく扱われるように修正してみます。

Step 4

ソリューションエクスプローラで、StatesDataSet.cs を追加します。

Image

partial class vEmployeeTableAdapter を実装します。(コードは、ほぼ参考文献1どおりなので、エラー、オブジェクト廃棄処理は適切に行ってください。)

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
using System.Data.SqlClient;

namespace DataSetStatesTableAdapters
{
    public partial class vEmployeeTableAdapter
    {
    [DataObjectMethod(DataObjectMethodType.Select)]
    public DataSetStates.vEmployeeDataTable Getdata(string state)
    {
    SqlDataAdapter sqlda;
    if (state == "ALL")
    {
        sqlda = new SqlDataAdapter("SELECT EmployeeID, FirstName, LastName,                     StateProvinceName, City FROM HumanResources.vEmployee", this.Connection);
    }
    else
    {
        if (state == null)
            return null;
        sqlda = new SqlDataAdapter("SELECT EmployeeID, FirstName, LastName, StateProvinceName, City FROM HumanResources.vEmployee WHERE StateProvinceName=@state", this.Connection);
        sqlda.SelectCommand.Parameters.AddWithValue("@state", state);
        }
        DataSetStates.vEmployeeDataTable table = new DataSetStates.vEmployeeDataTable();
        sqlda.Fill(table);
        return table;
        }
    }
}

すると、ObjectDataSource1 のメソッドの選択のところに、新たにメソッドが追加されます。

Image

このときのパラメータは、次のように与えます。

Image

これにより、ALL を選んだ場合でも正しく動作するようになります。

Image

同様に TOP N についても、ObjectDataSource にパラメータを取るメソッドを追加してあげることにより対応が可能となる。

さいごに

partial class TableAdapter への機能拡張で、そのためには内部的に自動作成されているコード(C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\websitetest1\???\???\Sources_App_Code) の中身を一度見ておくと、どのように機能を追加すればよいのか、すっきりすると思います。

そうしないと、どのクラスにどのように機能拡張しなければいけないのが手さぐりになってしまい、試行錯誤してしまいます。このあたりの使い勝手は、もう少し改良してもらいたいですね。

それに、こんな程度のものを3層なんて呼んでいていいのかね・・・これってSQL DataSource に少し毛が生えた程度ジャン orz