.net frameworkのDBトランザクションの種類

https://blogs.msdn.microsoft.com/nakama/2008/10/23/transactionscope/

ローカルトランザクション

ADO.NETだけで完結する普通のトランザクション
トランザクションオブジェクトやDB接続を持ち回らないとトランザクションを維持できない。

using (var conn = new SqlConnection("接続文字列")) {
	conn.Open();
	using (var tran = conn.BeginTransaction()) {
		using (var cmd = conn.CreateCommand()) {
			cmd.CommandText = "update AAAA set ...";
			cmd.Transaction = tran;
			cmd.ExecuteNonQuery();
		}
		using (var cmd = conn.CreateCommand()) {
			cmd.CommandText = "update BBBB set ...";
			cmd.Transaction = tran;
			cmd.ExecuteNonQuery();
		}
		tran.Commit();
	}
}

分散トランザクション

複数の別々のDBに対する接続で、まとめて1つのトランザクションを切ることができる仕組み。
MS-DTCというWindowsサービスを利用しているため、サービスが起動していない(できない)と正常に動作しない。

using (var tran = new System.Transaction.TransactionScope()) {
	executeSql("DB1へ接続する接続文字列", "update AAAA set ...");
	executeSql("DB2へ接続する接続文字列", "update BBBB set ...");

	tran.Commit();
}

void executeSql(string connStr, string sql) {
	using (var conn = new SqlConnection(connStr)) {
		using (var cmd = conn.CreateCommand()) {
			cmd.CommandText = sql;
			cmd.ExecuteNonQuery();
		}
	}
}

MS-DTCサービスが無効になっていたり設定がおかしい場合に、動作しないことが起こりうる!
しかもこれは実行環境に依存する問題なので面倒くさい。ユーザにこんな説明して設定を変えてもらうのは難しい。
http://redraccoondog35.cocolog-nifty.com/blog/2007/03/msdtc_ea75.html

Professional系のOSではMS-DTC(Distributed Transaction Coordinator)のサービスが無効になっているので、サービスを起動する必要がある。
WebサーバとDBサーバが異なるサーバの場合、MS-DTCのセキュリティの構成の設定を変更にする必要がある。
MS-DTCのセキュリティの構成を変更した後にMS-DTCのサービスは再起動されるが、関連するサービス(SQL ServerIISのサービス)も再起動する必要がある。

トランザクションの自動昇格

分散トランザクションは、必ずMS-DTCサービスを利用するわけではなく、
・対象となるデータベースが、SQL Server 2005以上 であること。
・TransactionScope 内で一つの物理コネクションのみを使うこと。
という条件が満たされているときは、内部的にはローカルトランザクションと同じ動きをしてくれる。
つまり……。
『「とりあえず MS-DTC を使わないですむのならがんばってみる」という挙動をし、ダメだとわかった時点で MS-DTC を使う分散トランザクションに自動昇格する』
…という動作をしてくれる。
「TransactionScope 内で一つの物理コネクションのみを使う」というのは、VS2008以降なら内部的にプールされている接続が閉じなければ「一つの物理コネクション」として判定してくれる。
つまり「分散トランザクション」で書いたコードはMS-DTC自動昇格『しない』で動作してくれる。
しかしこれ、「自動」なので昇格するかどうかがコードから解りづらい。ある修正が意図せず分散トランザクションへの昇格を引き起こすこともありえる。
(そして開発環境ではたまたまMSDTCが動いていてテスト成功するが本番環境でエラーが出るのだ)