WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

TableAdapterManager

by WebSurfer 21. December 2011 22:19

Visual Studio には、型指定された DataSet + TableAdapter をウィザードベースで自動生成する機能があります。さらに、Visual Studio 2008 以降では、階層更新を実現する TableAdapterManager クラスが追加で自動生成されるようになりました。

今さらながらですが、TableAdapterManager について調べて、いろいろ発見があったので忘れないように書いておきます。

TableAdapterManager を利用したアプリケーション

階層更新とは、簡単に言うと、複数のテーブルで構成される DataSet が持つ更新データを、データベースの整合性に関する規則(参照整合性規則)を守って、データベースに挿入、更新、削除するプロセスのことです。(詳しい説明は MSDN ライブラリの 階層更新 を参照してください)

例として、上の画像のような、Northwind サンプルデータベースの Customers と Orders テーブル両方を同時に管理するアプリケーションを考えます。(Customers テーブルは CustomerID を主キーとして持ち、Orders テーブルは CustomerID を外部キーとして持っています。)

新しい顧客から注文があった場合は、先に新しい顧客レコードを Customers テーブルに Insert してから、注文レコードを Orders テーブルに Insert しなければなりません。

Customers テーブルから顧客レコードを Delete する場合は、先に Orders テーブルの当該顧客の注文レコードをすべて Delete してからにしなければなりません。

さらに、Insert、Update、Delete の順序も重要です。例えば、Customers テーブルの既存のレコードの主キー値を変更する場合、以下のような手順にしなければなりません。

  1. Customers テーブルに、新しい CustomerID 値で、新しいレコードを Insert
  2. Orders テーブルの当該レコードの CustomerID を新しい値に Update
  3. Customers テーブルの旧 CustomerID のレコードを Delete

従って、Insert => Update => Delete の順で行う必要があります(TableAdapterManager のデフォルトがこれ。他に、Update => Insert => Delete とすることも可能)。

Visual Studio 2005 以前のバージョンでは、上記のような参照整合性規則を守って更新を行う(即ち、階層更新を実現する)ためのコードを自力で実装する必要がありました。具体的には以下ようなコードを実装しなければなりません。

  1. まず、DataTable の Select メソッドを使用して特定の RowState(Added、ModifiedCurrent、Deleted)を持つ行だけを参照する DataRow 配列を取得します。(DataAdapter によるデータ ソースの更新 の「挿入、更新、削除の順序」のセクション参照)
  2. その後、各テーブルの TableAdapter の Update(DataRow[]) メソッドを適切な順序で呼び出し、各テーブルから RowState 別に取得した DataRow 配列を適切な順序で渡して処理します。
  3. 当然ながらトランザクション処理も必要です。

Visual Studio 2008 から新しく追加された TableAdapterManager クラスには、階層更新を実現するロジックを持つ UpdateAll メソッドが実装されています。MS-DTC を使わない手動トランザクション処理も実装されています。

実際に、MSDN ライブラリのチュートリアル SQL Server Express データベースの作成SQL Server Express データベース内のデータへの接続 (Windows フォーム) を参考に、型指定された DataSet + TableAdapter を作って、その中の TableAdapterManager のコードを見てみました。(もっと詳しいチュートリアルがありました。下の 2011/12/22 追記の「その1」を参照ください)

TableAdapterManager の UpdateAll メソッドは、Customers => Orders の順で両方のテーブルに対して Insert を行い、次に Customers => Orders の順で両方のテーブルに対して Update を行い、そして、最後に Orders => Customers の順で両方のテーブルに対して Delete を行うというように、上に述べた参照整合性規則を守って更新を実行するためのコードが実装されているのが確認できました。

TableAdapterManager は万能ではないと思いますが、多くのケースで、自力で階層更新を実現するためのコードを書く必要がなくなったのではないでしょうか。

自動生成されたコードで対応できない場合は、TableAdapterManager クラスは partial として定義されているので、自力でコードを書いてそれを拡張すれば、Visual Studio 2005 以前のときと比べて比較的簡単に対応可能と思います。

------------- 2011/12/22 追記 -------------

その1

Customers テーブルと Orders テーブルを使ったアプリケーションの作成は、上記のページより、10 行でズバリ !! 非接続型のデータ アクセス (ADO.NET) (C#) の方が詳しく書いてあって、参考になると思います。

その2

単一テーブルのアプリケーションにおいて、既存のレコードを Delete して、そのレコードと同じ主キーを持つレコードを新たに Insert する場合、Delete => Insert の順でないとうまくいきません。

TableAdapterManager は、Insert => Update => Delete(デフォルト)または Update => Insert => Delete のいずれかしか更新順序は選べませんので、上記のケースには対応できないということになります。

本文に述べた Customers テーブルの既存のレコードの主キー値を変更するケースより、上記のケースの方が多そうな気がするのですが、Microsoft は何故 Delete を最初にしなかったのでしょう? 気になります。(2015/11/12 追記: Delete => Insert などという乱暴なことを許すと、ユーザーのミスで問題が出る可能性が高くなるからではないかと最近思い初めています。Update すれば済む話ですから)

Tags:

ADO.NET

TableAdapter と Transaction

by WebSurfer 18. December 2011 20:33

Visual Studio を利用してウィザードベースで自動生成する型付 DataSet + TableAdapter を使ってデータベースを更新する際、手動トランザクション処理するにはどうしたらいいでしょうか?(MS-DTC を使う自動トランザクションではなくて)

Visual Studio 2008 から TableAdapter に Transaction プロパティが追加されたので、それと、それ以前からある Connection プロパティを使えば、Visual Studio 2005 以前と比較して手動トランザクションが容易に設定できます。

でも、Visual Studio 2008 以降を使っているなら、そもそも手動トランザクションをかけるコードを自力で書く必要はなくて、自動生成される TableAdapterManager クラスの UpdateAll メソッドを使用すればいいです。

実は知らなかったのですが、TableAdapterManager.UpdateAll メソッドのコードをよく見てみると、そのメソッドの中でトランザクションがかかるようになってました。

もともと、TableAdapterManagerは 階層更新 を実現する ため(即ち、複数のテーブルを、データベース内の制約によって定義される一貫性規則を守って���連レコードの挿入、更新、および削除を制御するため)のものということらしいですが、単一テーブルの場合もトランザクションは有効に働きます。

という訳で、Visual Studio 2008 以降なら TableAdapterManager の UpdateAll メソッドを使うのが正解だと思います。

ちなみに、Visual Studio 2005 以前の場合は Transaction プロパティは自動生成されたコードには定義されません。TableAdapter は partial クラスとして定義されているので、自動生成されたファイルとは別に、Visual Studio 2008 以降で生成されるコードを参考に、自力で Transaction プロパティを定義して使うのがいいと思います。SqlClient の場合は以下のような感じです。

private System.Data.SqlClient.SqlTransaction _transaction;

internal System.Data.SqlClient.SqlTransaction Transaction {
  get {
    return this._transaction;
  }
  set {
    this._transaction = value;
    for (int i = 0; i < this.CommandCollection.Length; i++) {
      this.CommandCollection[i].Transaction = this._transaction;
    }
    if (((this.Adapter != null) 
        && (this.Adapter.DeleteCommand != null))) {
      this.Adapter.DeleteCommand.Transaction = this._transaction;
    }
    if (((this.Adapter != null) 
        && (this.Adapter.InsertCommand != null))) {
      this.Adapter.InsertCommand.Transaction = this._transaction;
    }
    if (((this.Adapter != null) 
        && (this.Adapter.UpdateCommand != null))) {
      this.Adapter.UpdateCommand.Transaction = this._transaction;
    }
  }
}

どうも、Visual Studio 2008 から TableAdapter に Transaction プロパティが追加された理由は、TableAdapterManager.UpdateAll メソッドで手動トランザクションをかけるためのようです。

Tags: ,

ADO.NET

Access 2007 の DB を利用するアプリ開発

by WebSurfer 8. November 2011 22:37

注意 1:
2010, 2013 用のドライバには 32/64-bit 版の両方があります(2007 用は 32-bit のみ)。Visual Studio は 32-bit ですので、ドライバに 64-bit 版を使うと、この記事に書いたような Visual Studio の Access DB への接続はできませんので注意してください。

注意 2:
下にリンクを張ったダウンロードページ「Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント」の「詳細」にある条件に "Jet の全般的な代替としての使用" はできないと書いてあります。一方 Microsoft Access 2010 を使用したデータ プログラミングには JET は非推奨だから ACE を使おうという意味のことが書いてあります。一体どうしろと言うのでしょうね。(汗)

Access 2007 をインストールしていない開発環境でも、Access 2007 データベース(accdb ファイル)を使用するアプリケーションを開発できます。

Microsoft.ACE.OLEDB.12.0 プロバイダの選択

Access 2003 以前で使用されていた JET (Joint Engine Technology) データベースエンジンは、Access 2007 では ACE (Access Connectivity Engine) データベースエンジンに代わったそうです。そのため、ACE データベースエンジン用のドライバが必要になります。

Microsoft ダウンロードセンターの 2007 Office system ドライバ: データ接続コンポーネントから AccessDatabaseEngine.exe をダウンロードして開発マシンにインストールすれば、ACE データベースエンジン用の OLEDB ドライバと ODBC ドライバが利用可能になります。

2019/6/24 追記: Office 2007 がサポートされなくなったためか、上の 2007 用のページはリンク切れとなってしまいました。探しても見つからないので、今現在は 2010 以降用を使うほかなさそうです。2010 用は以下からダウンロードできます。

Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント

(ちなみに、JET 4.0 データベースエンジン用の OLEDB プロバイダ、ODBC ドライバは Windows OS 同梱で提供されているのでインストールは不要だそうです。Jet データベース エンジンを使用するアプリケーションの開発/動作環境 を参照ください)

インストールすると、Visual Studio 2010 を Access 2007 のデータベース(accdb ファイル)に接続できるようになります。

上の画像は、Microsoft が提供しているサンプルデータベース "Northwind 2007.accdb" を Web アプリケーションルート直下の App_Data フォルダにコピーして、Visual Studio 2010 のサーバーエクスプローラーの「接続の追加」メニューから「詳細設定」を開き、"Northwind 2007.accdb" に接続しているところです。

接続できれば、Access 2003 の mdb ファイルと同様に、AccessDataSource や ObjectDataSource を利用して Access 2007 データベース(.accdb ファイル)を操作するアプリケーションを、ウィザードベースで作成できるようになります。

Tags: ,

ADO.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  October 2021  >>
MoTuWeThFrSaSu
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

View posts in large calendar