TransactionScopeはどのようにトランザクションをロールバックしますか?


99

複数のオブジェクトをデータベースに挿入する統合テストを作成していて、メソッドがそれらのオブジェクトを取得するかどうかを確認しています。

データベースへの接続はNHibernateを介して行われます。そのようなテストを作成するための通常の方法は次のようにすることです。

NHibernateSession.BeginTransaction();

//use nhibernate to insert objects into database
//retrieve objects via my method
//verify actual objects returned are the same as those inserted

NHibernateSession.RollbackTransaction();

しかし、最近この目的に使用できると思われるTransactionScopeについて最近知りました...

私が見つけたいくつかのサンプルコードは次のとおりです:

public static int AddDepartmentWithEmployees(Department dept)
{

    int res = 0;

    DepartmentAdapter deptAdapter = new DepartmentAdapter();
    EmployeeAdapter empAdapter = new EmployeeAdapter();
    using (TransactionScope txScope = new TransactionScope())
    {

        res += deptAdapter.Insert(dept.DepartmentName);
        //Custom method made to return Department ID 
        //after inserting the department "Identity Column"
        dept.DepartmentID = deptAdapter.GetInsertReturnValue();
        foreach(Employee emp in dept.Employees)
        {

            emp.EmployeeDeptID = dept.DepartmentID;
            res += empAdapter.Insert(emp.EmployeeName, emp.EmployeeDeptID);

        }
        txScope.Complete();

    }
    return res;

}

txScope.Complete()を含めないと、挿入されたデータはロールバックされると思います。しかし残念ながら、私はそれが可能であるかを理解していない...どのようにtxScopeオブジェクトがのトラックおくdeptAdapterと、empAdapterデータベース上のオブジェクトとその取引を。

ここに少し情報が欠けているように感じます... を使用してコードを囲むことで、私の呼び出しBeginTransaction()RollbackTransaction()呼び出しを本当に置き換えることができTransactionScopeますか?

そうでない場合、TransactionScopeトランザクションはどのようにロールバックされますか?


私はNHibernateを使用したことがありませんが、おそらくこのリンクが役立つでしょう。

あなたがトランザクションにグループ操作にあなたNHibernateのセッションを管理するためのより良い方法を見ている場合は、そのトピックに私のブログの記事をチェックアウトする場合がありますdotnetchris.wordpress.com/2009/01/27/...
クリスMarisic

回答:


107

基本的に、TransactionScopeはアダプターを追跡しません。データベース接続を追跡します。DB接続を開くと、アンビエントトランザクション(トランザクションスコープ)が存在するかどうかが確認され、存在する場合はそれに参加します。同じSQLサーバーへの接続が複数ある場合は、分散トランザクションにエスカレーションされます。

usingブロックを使用しているため、例外が発生した場合でも、必ずdisposeが呼び出されるようになります。したがって、txScope.Complete()の前にdisposeが呼び出された場合、TransactionScopeは接続にトランザクション(またはDTC)をロールバックするよう指示します。


10
TransactionScopeは、スレッド上の現在のトランザクション以外は何も追跡せず、モデルに基づいて必要な場合はそれを変更します(必要、新規が必要など)。トランザクションは、データベース接続だけでなく、参加するすべてのものに通知するだけです。
casperOne 2009年

1
これは完全に真実ではないと思います。TransactionScopeのソースコードの部分的なトレースを実行しました。また、このmsdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx が「トランザクションを作成しなかった場合、 CommittableTransactionオブジェクトの所有者によってCommitが呼び出されるたびにコミットが発生します。その時点で、トランザクションマネージャはリソースマネージャを呼び出し、TransactionScopeオブジェクトでCompleteメソッドが呼び出されたかどうかに基づいて、コミットまたはロールバックを通知します。ソーストレースもこの動作を示しています。
user44298 2011年

私はこのSO Q&Aが役に立ったと感じました:IEnlistmentNotification
mungflesh

まだはっきりしない。トランザクションスコープ内で呼び出されるメソッドを持つオブジェクトは、トランザクションメカニズムと連携している必要があります。彼らはシステムによるコミット/ロールバック通知を探し、必要なときにロールバックを実行するものであるため、ロールバックできる必要があります(ファイルの削除が実行された場合、明らかに、いくつかの予防策)。また、SQLサーバーの操作は協調的です。しかし、.Netには他の協調オブジェクトがありますか?そして協力的なクラスをどのように書くのですか?ドキュメンテーション?

54

TransactionScopeクラスはで動作するTransactionクラススレッド固有です、。

ときTransactionScopeに作成され、それはそこにあるかどうかをチェックしTransactionたスレッドのために。存在する場合はそれを使用し、存在しない場合は新しいものを作成してスタックにプッシュします。

既存のものを使用する場合は、リリースのカウンターをインクリメントします(呼び出す必要があるためDispose)。最後のリリースでは、Transactionがコミットされなかった場合、すべての作業がロールバックされます。

クラスがトランザクションについて魔法のように知っているように見える理由については、それがこのモデルで動作するクラスの実装の詳細として残されています。

deptAdapteremptAdapterインスタンスを作成すると、スレッド(スレッドのクラスの静的CurrentプロパティTransaction)に現在のトランザクションがあるかどうかが確認されます。存在する場合は、それ自体をに登録してTransaction、コミット/ロールバックシーケンスに参加します(これTransactionは、カーネル、分散などのさまざまなトランザクションコーディネーターを制御し、伝達する可能性があります)。


4
スコープ内で作成されたSqlConnectionでどのように機能しますか?SqlConnectionクラスは、TransactionScopeに参加するTransactionクラスを内部的に使用しますか?それとも直接TLSに参加しますか?
Kakira 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.