分散トランザクション
適用対象: .NET Framework .NET .NET Standard
トランザクションとは、たとえば、1 つの単位として成功 (コミット) または失敗 (アボート) する関連タスク セットです。 "分散トランザクション" は、複数のリソースに影響するトランザクションです。 分散トランザクションがコミットされるためには、すべての参加要素が、すべてのデータ変更が永久的な変更となることを保証する必要があります。 システム クラッシュその他の予期しない出来事が発生した場合でも、変更は保持されます。 1 つの参加要素がこの保証に失敗しただけでも、トランザクション全体が失敗し、トランザクションのスコープ内のデータに対する変更がロールバックされます。
Note
Azure SQL Database および Azure SQL Managed Instance での分散トランザクションの詳細については、「クラウド データベースにまたがる分散トランザクション」を参照してください。
System.Transactions の操作
.NET では、分散トランザクションは System.Transactions 名前空間の API によって管理されます。 複数の永続的なリソース マネージャーが関係する場合、System.Transactions API は分散トランザクション処理を Microsoft Distributed Transaction Coordinator (MS DTC) などのトランザクション モニターに委任します。 詳しくは、「トランザクションの基礎」をご覧ください。
ADO.NET 2.0 では、EnlistTransaction
メソッドを使用した分散トランザクションへの参加のサポートが導入されました。これにより、接続を Transaction インスタンスに参加させることができます。 ADO.NET の以前のバージョンでは、分散トランザクションへの明示的な参加は、接続の EnlistDistributedTransaction
メソッドを使用して実行されていました。これによって ITransaction インスタンス内の接続を参加させることで、下位互換性を得ることができます。 Enterprise Services トランザクションについて詳しくは、「Enterprise Services および COM+ トランザクションとの相互運用性」をご覧ください。
Microsoft SqlClient Data Provider for SQL Server で SQL Server データベースに対して System.Transactions トランザクションを使用する場合は、軽量な Transaction が自動的に使用されます。 トランザクションは、必要に応じて完全な分散トランザクションに昇格させることができます。 詳細については、「SQL Server と System.Transactions の統合」を参照してください。
分散トランザクションへの自動参加
自動参加は、ADO.NET 接続を System.Transactions
に統合する場合の既定の (推奨される) 方法です。 接続オブジェクトは、トランザクションがアクティブであると判定されると、既存の分散トランザクションに自動的に参加します。トランザクションがアクティブであることは、System.Transaction
から見ると、Transaction.Current
が null でないことを意味します。 自動トランザクション参加は、接続が開かれた場合に行われます。 その後は、コマンドがトランザクションのスコープ内で実行された場合でも、自動トランザクション参加は行われません。 SqlConnection.ConnectionString の接続文字列パラメーターとして Enlist=false
を指定することで既存のトランザクションで自動登録を無効にできます。
分散トランザクションへの手動登録
自動登録が無効になっているか、接続の確立後に開始されたトランザクションを登録する必要がある場合、Microsoft SqlClient Data Provider for SQL Server の SqlConnection オブジェクトの EnlistTransaction
メソッドを利用し、既存の分散トランザクションに登録できます。 既存の分散トランザクションに参加すると、トランザクションがコミットまたはロールバックされた場合、データ ソースに対してコードで行った変更もコミットまたはロールバックされます。
Note
トランザクションがアクティブであるときに DataReader
が開始された場合、トランザクションをコミットまたはロールバックしようとすると例外がスローされます。
分散トランザクションへの参加は、特にビジネス オブジェクトをプールする場合に適切です。 ビジネス オブジェクトが、開かれている接続と共にプールされている場合は、その接続を開くときだけ、自動トランザクション参加が行われます。 プールされているビジネス オブジェクトを使用して複数のトランザクションが実行される場合、そのオブジェクトの開かれている接続は、新しく開始されるトランザクションには自動参加しません。 この場合には、接続の自動トランザクション参加を無効にし、EnlistTransaction
を使用して、接続をトランザクションに参加させることができます。
EnlistTransaction
は、既存のトランザクションを参照する Transaction 型の引数を 1 つ受け取ります。 接続の EnlistTransaction
メソッドを呼び出した後、接続を使用してデータ ソースに対して行ったすべての変更は、トランザクションに組み込まれます。 null 値を渡すことで、現在の分散トランザクションから接続の参加が解除されます。 この接続は、EnlistTransaction
を呼び出す前に開く必要があることに注意してください。
Note
一度接続を明示的にトランザクションに参加させると、最初のトランザクションが終了するまでは、参加を解除したり別のトランザクションに参加させたりすることはできません。
注意事項
接続の EnlistTransaction
メソッドを使用してトランザクションが既に開始していた場合、BeginTransaction は例外をスローします。 ただし、トランザクションがデータ ソースで開始されたローカル トランザクションである場合 (たとえば SqlCommand を使用して BEGIN TRANSACTION ステートメントを明示的に実行した場合)、EnlistTransaction
はローカル トランザクションをロールバックし、要求されたように既存の分散トランザクションに参加します。 ローカル トランザクションがロールバックされたことは通知されないため、BeginTransaction を使用して開始したのではないローカル トランザクションについては、自分で管理する必要があります。 Microsoft SqlClient Data Provider for SQL Server を SQL Server で使用する場合、登録しようとすると例外がスローされます。 その他の場合については検出されません。
SQL Server で昇格可能なトランザクション
SQL Server は、軽量のローカル トランザクションを必要に応じて分散トランザクションに自動的に昇格できる、昇格可能なトランザクションをサポートしています。 昇格可能なトランザクションは、必要な場合以外、分散トランザクションのオーバーヘッドの増加を引き起こすことはありません。 詳細とコード サンプルについては、「SQL Server と System.Transactions の統合」を参照してください。
分散トランザクションの設定
分散トランザクションを使用するには、ネットワーク上の MS DTC を有効にする必要があります。 サーバーのローカル Windows ファイアウォールが有効になっている場合は、MS DTC サービスでネットワークを使用するか MS DTC ポートを開けるようにする必要があります。