MSDTCが止まっている状態でTransactionScopeは使えないため、代わりの方法を試してみました。
決してきれいな方法ではないです。
TableAdapterのPartialクラス定義を考慮すればもう少しマシになると思いますが、それでも無理矢理な感じは否めない。
やっぱり素直に TransactionScope を使いましょう。
サンプルとして、みんなのお約束 Northwind を使います。
(下のコードの処理自体は全く無意味)
1. Windowsアプリのプロジェクトを新規作成
2. DataSetを追加。
3. Customers(列は CustomerID, CompanyName, City)テーブルとSuppliers(列はSupplierID, CompanyName, City)のTableAdapterを追加
4. CustomersTableAdapter(SuppliersTableAdapterでもいいけど) で右クリック→[コードの表示]
5. こんな感じでコード入力。
Partialクラスで privateなAdapterプロパティを外に引きずり出します。とりあえずの実験コードでここがかっこ悪いのでちゃんと作るならばこのクラス内でSqlTransaction が関わる処理を隠蔽するべきでしょうね。
using System.Data;
using System.Data.SqlClient;
namespace TranTest.NorthwindDataSetTableAdapters
{
partial class CustomersTableAdapter
{
public SqlDataAdapter MyAdapter
{
get { return this.Adapter; }
}
}
partial class SuppliersTableAdapter
{
public SqlDataAdapter MyAdapter
{
get { return this.Adapter; }
}
}
}
6. Windowsフォームのコードにこんな感じで入力。
フォームにコマンドボタンを1つ貼り付けておきました。
"supplierAdapter.MyAdapter.InsertCommand.Transaction = tran;" あたりがかっこ悪すぎ。
private void button1_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(接続文字列);
conn.Open();
NorthwindDataSetTableAdapters.CustomersTableAdapter customerAdapter = new NorthwindDataSetTableAdapters.CustomersTableAdapter();
customerAdapter.Connection = conn;
NorthwindDataSetTableAdapters.SuppliersTableAdapter supplierAdapter = new NorthwindDataSetTableAdapters.SuppliersTableAdapter();
supplierAdapter.Connection = conn;
SqlTransaction tran = conn.BeginTransaction();
try
{
supplierAdapter.MyAdapter.InsertCommand.Transaction = tran;
supplierAdapter.Insert("Supplier Test", "Tokyo");
customerAdapter.MyAdapter.InsertCommand.Transaction = tran;
customerAdapter.Insert("CUST1", "Customer Test", "Tokyo");
tran.Commit();
MessageBox.Show("コミットしました");
}
catch (SqlException)
{
tran.Rollback();
MessageBox.Show("ロールバックしました");
}
finally
{
conn.Close();
}
}
7. 実行すると 1回目はコミット、2回目以降はロールバックするはずです。
念のため、TransactionScopeを使った自動トランザクションならば、こんなコードになるはず。
private void button1_Click(object sender, EventArgs e)
{
using (TransactionScope ts = new TransactionScope())
{
try
{
NorthwindDataSetTableAdapters.CustomersTableAdapter customerAdapter = new NorthwindDataSetTableAdapters.CustomersTableAdapter();
customerAdapter.Insert("CUST1", "Customer Test", "London");
NorthwindDataSetTableAdapters.SuppliersTableAdapter supplierAdapter = new NorthwindDataSetTableAdapters.SuppliersTableAdapter();
supplierAdapter.Insert("Supplier Test", "London");
ts.Complete();
MessageBox.Show("コミットしました");
}
catch (SqlException)
{
MessageBox.Show("ロールバックしました");
}
}
}