連載
» 2008年04月25日 00時00分 公開

連載:Visual Studio 2005によるWindowsデータベース・プログラミング:第8回 テーブルアダプタでトランザクション (3/4)

[遠藤孝信,デジタルアドバンテージ]

トランザクションの実装

 それではトランザクション処理の実装に入っていきましょう。.NETでトランザクション処理を行うには、主に次の2つの方法があります。

(1)System.Data.SqlClient名前空間のSqlTransactionクラスを利用する
(2)System.Transactions名前空間のTransactionScopeクラスを利用する

 (1)はマニュアル・トランザクションと呼ばれるもので、トランザクション(SqlTransactionオブジェクト)を作成し、SQL文を含んだコマンド(SqlCommandオブジェクト)をトランザクションに参加させ、最後にコミット/ロールバックを行うという、昔ながらのプログラミング・モデルです。

 これに対し、(2)は.NET Framework 2.0から利用可能な新しい方法で、自動トランザクション(あるいは「暗黙的なトランザクション」)と呼ばれています。これは、トランザクション(TransactionScopeオブジェクト)を作成するだけで、それ以降に行うSQL処理を自動的にトランザクションに参加させることができます。

 今回では、新しくて便利な(はず)の(2)のTransactionScopeクラスを使ってトランザクション処理を行います。本連載では、テーブルアダプタが持つメソッドによってのみデータベース処理を行っていますので(といっても、使っているのはFillメソッドとUpdateメソッドだけですが)、自動的にトランザクションに参加できる(2)が便利です。

■TransactionScopeクラスによるトランザクション

 TransactionScopeクラスの使い方は簡単で、大枠は次のようなコーディングになります。

……

' トランザクションの始まり
Using scope As New System.Transactions.TransactionScope()

  '
  ' データベースのアクセス処理
  '

  scope.Complete() ' コミット

End Using ' トランザクションの終わり

……

TransactionScopeクラスによるトランザクション処理の記述

 このリストでは、Using 〜 End Usingまでの間で実行したデータベースの処理が1つのトランザクションとなります。TransactionScopeクラスをインスタンス化すれば、それがトランザクションの始まりとなります*3

*3 TransactionScopeクラスのコンストラクタでは、パラメータにより、実行されるコードが参加するトランザクションを制御することもできます。コードが現在参加しているトランザクションは「アンビエント・トランザクション」と呼ばれます。アンビエント(ambient)とは「周囲の」「環境の」という意味です。


 トランザクションをコミットするには、Completeメソッドを呼び出します。ロールバックするにはTransactionScopeメソッドのDisposeメソッドを呼び出せばよいのですが、Usingステートメントを使っているので、Using 〜 End Usingを抜けるだけで、自動的にDisposeメソッドが呼び出されます(正確には、Completeメソッドによりトランザクションが成功したことを示し、Disposeメソッド呼び出し時にコミットあるいはロールバックが行われます)。

 なお、TransactionScopeクラスはSystem.Transactions.dllで実装されており、このDLLファイルはデフォルトではプロジェクトから参照されていませんので、次の図のようにして参照の追加を行う必要があります。

図8 System.Transactions.dllへの参照の追加
ソリューション・エクスプローラでプロジェクト名を右クリックし、メニューから[参照の追加]を実行すると、このダイアログが開く。ここで「System.Transactions」を選択して[OK]ボタンをクリックする。

■サンプル・アプリケーションにおけるTransactionScopeクラスの利用

 それではTransactionScopeクラスを利用して、サンプル・アプリケーションにトランザクション処理を実装しましょう。実は環境の問題により、このままでは実行時にエラーとなるのですが、コードは次のようになります。前回で作成したコードに、UsingとEnd Using、そしてコミットを行うための「scope.Complete()」の3行を追加しただけです。

Private Sub 注文BindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 注文BindingNavigatorSaveItem.Click

  Me.Validate()
  Me.注文BindingSource.EndEdit()
  Me.注文明細BindingSource.EndEdit()

  Dim rows() As DataRow


  ' トランザクションの始まり
  Using scope As New System.Transactions.TransactionScope()

    ' 注文明細テーブルの削除処理
    rows = Me.NORTHWNDDataSet.注文明細.Select( _
                    "", "", DataViewRowState.Deleted)
    If rows.Length <> 0 Then
      Me.注文明細TableAdapter.Update(rows)
    End If


    ' 注文テーブルの削除処理
    rows = Me.NORTHWNDDataSet.注文.Select( _
                    "", "", DataViewRowState.Deleted)
    If rows.Length <> 0 Then
      Me.注文TableAdapter.Update(rows)
    End If


    ' 注文テーブルの追加・変更処理
    rows = Me.NORTHWNDDataSet.注文.Select("", "", _
      DataViewRowState.Added Or DataViewRowState.ModifiedCurrent)
    If rows.Length <> 0 Then
      Me.注文TableAdapter.Update(rows)
    End If


    ' 注文明細テーブルの追加・変更処理
    rows = Me.NORTHWNDDataSet.注文明細.Select("", "", _
      DataViewRowState.Added Or DataViewRowState.ModifiedCurrent)
    If rows.Length <> 0 Then
      Me.注文明細TableAdapter.Update(rows)
    End If


    scope.Complete() ' トランザクションのコミット

  End Using ' トランザクションの終わり

End Sub

トランザクション処理を追加した[データの保存]ボタンのイベント・ハンドラ

 アプリケーションを実行し、試しに先ほどと同じように注文データを削除してから[データの保存]ボタンをクリックしてみましょう。恐らく2番目のUpdateメソッド呼び出しで、次のようなエラーが出るはずです。

図9 「MSDTCは使用できません」というエラーが発生

 「コンピュータでMSDTCは使用できません」というエラーが出ています。「MSDTC」とは何でしょうか?

 MSDTCは「Microsoft Distributed Transaction Coordinator」の略で、Windowsサービスの1つです。日本語では「分散トランザクション・コーディネイタ」と呼ばれます。Windowsのサービス一覧を確認してみると、このサービスが停止状態になっているはずです。

図10 Windowsサービスの1つであるMSDTC
この[サービス]ダイアログは、コントロール・パネルの[管理ツール]−[サービス]を実行して開くことができる。

 このサービスを開始しておくと、確かにアプリケーションは問題なく動作するわけですが、1台のコンピュータ上ですべてを行っているのに分散トランザクションとは一体何事でしょうか?

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。