C#で複数のDB(PostgreSQL)に対して登録/更新処理を行う必要があり、トランザクション処理としてはTransactionScopeを使用するとQiitaでの投稿があったので早速実装。
しかし、Completeを実行していなくてもDMLでコミットされてしまっている。更にネットで検索してみると、どうやらPostgreSQLでは下記のように接続文字列にEnlist=trueが必要らしい。ロジックでの書き方もある模様。
Server=localhost;User id=hoge;password=hoge;Enlist=true
追記して実行してみると、コミットは回避されたが、今度は2つ目のDBに対して更新を行うと、TransactionScopeがDisposeされるタイミングでトランザクション例外が発生してしまう。TransactionScopeをネストしてDB単位で処理してみることに。
using (var ts = new TransactionScope()){
using (var ts1 = new TransactionScope()){
ts1.Complete();
}
using (var ts2 = new TransactionScope()){
ts2.Complete();
}//ここを抜けると例外
ts.Complete();
}
同様に例外発生。
どうやらTransactionのスコープに問題があるようで、最終的には以下のように落ち着いた。
using (var ts = new TransactionScope()){
using (var ts1 = new TransactionScope(TransactionScopeOption.RequiresNew)){
ts1.Complete();
}
using (var ts2 = new TransactionScope(TransactionScopeOption.RequiresNew)){
ts2.Complete();
}
ts.Complete();
}
ts1にはTransactionScopeOption.RequiresNewがなくても良かったかと。