TransactionScope (2)
これ の続き。TransactionScope の動作についてのメモ。
使用するテーブル
CREATE TABLE Table1 ( ID INT PRIMARY KEY, NAME NVARCHAR(10) )
ネストしない場合
メソッド Insert は、DBへの接続をオープンして Table1 にデータを追加後接続をクローズする。
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1"); this.Insert(2, "name2"); } -- RESULT | ID | NAME | | NULL | NULL |
これは予想通り。
Complete を予想外の場所で呼ぶと
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { root.Complete(); this.Insert(1, "name1");// A this.Insert(2, "name2");// B } -- RESULT | ID | NAME | | NULL | NULL |
A で InvalidOperationException がスローされる。
さらに Complete の場所を変えると
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1");// A root.Complete(); this.Insert(2, "name2");// B } -- RESULT | ID | NAME | | 1 | name1 |
今度は B で InvalidOperationException がスローされるが、A の Insert はコミットされている。
ネストした場合
普通の使い方はこんな感じかな。
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1");// A using (TransactionScope nest = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(2, "name2");// B nest.Complete(); } root.Complete(); } -- RESULT | ID | NAME | | 1 | name1 | | 2 | name2 |
ネストされた TransactionScope の Complete をコメントアウトしてみる。
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1");// A using (TransactionScope nest = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(2, "name2");// B //nest.Complete(); } root.Complete(); }// C -- RESULT | ID | NAME | | NULL | NULL |
すると C で System.Transactions.TransactionAbortedException がスローされる。
今度はルート TransactionScope の Complete をコメントアウトしてみる。
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1");// A using (TransactionScope nest = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(2, "name2");// B nest.Complete(); } //root.Complete(); }// C -- RESULT | ID | NAME | | NULL | NULL |
ネストされた TransactionScope の Complete は無視される。MSDN で全ての TransactionScope の Complete が呼ばれた場合のみコミットされると書いてあったので、まあ予想通り。
この状態でネストされた TransactionScopeOption を変えてみると
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1");// A using (TransactionScope nest = new TransactionScope(TransactionScopeOption.RequiresNew)) { this.Insert(2, "name2");// B nest.Complete(); } //root.Complete(); }// C -- RESULT | ID | NAME | | 2 | name2 |
今度は Complete のコメントアウトを逆にしてみる。
using (TransactionScope root = new TransactionScope(TransactionScopeOption.Required)) { this.Insert(1, "name1");// A using (TransactionScope nest = new TransactionScope(TransactionScopeOption.RequiresNew)) { this.Insert(2, "name2");// B //nest.Complete(); } root.Complete(); }// C -- RESULT | ID | NAME | | 1 | name1 |