« XML Notepad 2007 | メイン | Expression Blend RC »

TableAdapterで手動トランザクションを使う方法

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("ロールバックしました");
        }
    }
}

About

2007年03月27日 11:41に投稿されたエントリーのページです。

ひとつ前の投稿は「XML Notepad 2007」です。

次の投稿は「Expression Blend RC」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Powered by
Movable Type 3.34