- 追加された行はこの色です。
- 削除された行はこの色です。
[[Open棟梁Project>http://opentouryo.osscons.jp/]] - [[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]
「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。
* 目次 [#p9eac4f1]
#contents
*概要 [#w9d80f60]
TransactionScopeクラスは、2相コミットを実現するための.NET 2.0のAPIであり、~
内部的には、トランザクション マネージャ(TM)・リソース マネージャ(RM)である[[MS-DTC]]を使用している。
*経緯 [#x3536ebe]
ASP.NET 1.xでは、[[MS-DTC]]は[[Enterprise Services>MS-DTC#h37e6c88]]上からの利用に限られたが、[[Enterprise Services>MS-DTC#h37e6c88]]を使用した場合、ビジネス プロセス・ビジネス コンポーネントなどのアプリケーション ブロックが[[Enterprise Services>MS-DTC#h37e6c88]]上に切り出す必要があったが、[[Enterprise Services>MS-DTC#h37e6c88]]アプリケーション開発は難易度が高く、あまり活用されなかった。このため、ASP.NET 2.0からは、上記のTransactionScopeクラスを利用することで、中間層を用いないで、ASP.NET上から簡単に2相コミットを利用できるように改善が図られた([[Windows DNA>MS-DTC#z4b553a3]]のASP上から[[MS-DTC]]を利用する方式に近い)。
-ASP.NET 1.xでは、
--[[MS-DTC]]は[[Enterprise Services>MS-DTC#h37e6c88]]上からの利用に限られたが、[[Enterprise Services>MS-DTC#h37e6c88]]を使用した場合、~
ビジネス プロセス・ビジネス コンポーネントなどのアプリケーション ブロックが[[Enterprise Services>MS-DTC#h37e6c88]]上に切り出す必要があった。
--また、[[Enterprise Services>MS-DTC#h37e6c88]]アプリケーション開発は難易度が高く、あまり活用されなかった。
-このため、ASP.NET 2.0からは、
--上記のTransactionScopeクラスを利用することで、[[Enterprise Services>MS-DTC#h37e6c88]]などの中間層を用いないで、~
ASP.NET上から簡単に2相コミットを利用できるように改善が図られた([[Windows DNA>MS-DTC#z4b553a3]]のASP上から[[MS-DTC]]を利用する方式に近い)。
--なお、TransactionScopeクラスは、[[WCF]]の[[Binding>Binding (ネットワーク)]]がサポートするWS-AtomicTransactionでもインターフェイスの定義がされたが、~
こちらの実装は、ほぼ実用化に至らず、その後、[[WS-I等の標準化団体も解散してしまった>Binding (ネットワーク)#oe20ef36]]。
*動作確認用のサンプル プログラム(ASP.NET) [#f286d476]
2相コミットの動作確認用サンプル プログラムを用いて、TransactionScopeクラスの利用方法を説明する。
**SQL Server [#n96e60bd]
下記は、SQL Server用のデータ アクセス ライブラリである、~
SqlClientを利用した場合のサンプル コード。
private void Two_Phase_Commit(bool flag)
{
TransactionOptions txopt = new TransactionOptions();
txopt.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.Snapshot;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, txopt))
{
using (SqlConnection con = new SqlConnection(@"Data Source=AAA;Initial Catalog=northwind;User ID=xxx;Password=xxx;"))
{
using (SqlCommand com = new SqlCommand())
{
com.Connection = con;
com.CommandText = "insert into table1(bbb) values('データ')";
try
{
con.Open();
com.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
using (SqlConnection con = new SqlConnection(@"Data Source=BBB;Initial Catalog=northwind;User ID=xxx;Password=xxx;"))
{
using (SqlCommand com = new SqlCommand())
{
com.Connection = con;
com.CommandText = "insert into table1(bbb) values('データ')";
try
{
con.Open();
com.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
if (flag) // flag変数はコミット、ロールバックのテストのための実装
{
scope.Complete();
}
else{ }
}
}
-分離レベルの選択が可能。Snapshot分離レベルは、SQLServer2005以降でサポートされる。
-using (TransactionScope scopeのUsingステートメント範囲内のTransactionScopeオブジェクトの破棄までがトランザクション範囲となる~
(Usingステートメント コードブロックは、範囲外に出る際に、自動的にオブジェクトのDispose()メソッドを呼び出す仕様になっている)。
-このため、Usingステートメントを使用しない実装をする際は手動でTransactionScope.Dispose()メソッドを呼び出す必要がある。
-最後に、TransactionScope.Complete()メソッドを呼び出し、上記のプログラム中の2つの接続が持つトランザクションは分散トランザクションとして2相コミットされる。
-TransactionScope.Complete()メソッドを呼び出さない状態でTransactionScopeオブジェクトが破棄された(Usingステートメントは、範囲外に出た)場合は、分散トランザクションは、ロールバックされる。
*Oracle [#m90a6c30]
下記は、Oracle用のデータ アクセス ライブラリである、System.Data.OracleClient、ODP.NETを利用した場合のサンプル コードである。実装を見てわかるとおり、ADO.NETの仕様に合わせ、APIのインターフェイスも共通化されているため、他のDBMSの[[データプロバイダ>ADO.NETデータプロバイダ]]も含め、実装に大きな違いは無い。
-下記は、Oracle用のデータ アクセス ライブラリである、System.Data.OracleClient、ODP.NETを利用した場合のサンプル コードである。
-実装を見てわかるとおり、ADO.NETの仕様に合わせ、APIのインターフェイスも共通化されているため、他のDBMSの[[データプロバイダ>ADO.NETデータプロバイダ]]も含め、実装に大きな違いは無い。
private void Two_Phase_Commit(bool flag)
{
TransactionOptions txopt = new TransactionOptions();
txopt.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.Snapshot;
//txopt.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, txopt))
{
using (OracleConnection con = new OracleConnection(@"User Id=xxx;Password=xxx;Data Source=AAA/orcl;"))
{
using (OracleCommand com = new OracleCommand())
{
com.Connection = con;
com.CommandText = "insert into table1(aaa, bbb) values(1, 'データ')";
try
{
con.Open();
com.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
using (OracleConnection con = new OracleConnection(@"User Id=xxx;Password=xxx;Data Source=BBB/orcl;"))
{
using (OracleCommand com = new OracleCommand())
{
com.Connection = con;
com.CommandText = "insert into table1(aaa, bbb) values(1, 'データ')";
try
{
con.Open();
com.ExecuteNonQuery();
}
finally
{
con.Close();
}
}
}
if (flag) // flag変数はコミット、ロールバックのテストのための実装
{
scope.Complete();
}
else{ }
}
}
*MS-DTC環境の構築 [#l6c42585]
詳しくはマニュアルなどを参照して下さい。~
(コチラを調べてから随分と期間が空いているので、設定方法も変わっていると思われるため)。