私は、データベースに多くのオブジェクトを挿入し、メソッドがそれらのオブジェクトを取得するかどうかを確認する統合テストを書いています。
データベースへの私の接続は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
オブジェクトとそれらのデータベース上のトランザクションをどのように追跡するのか。
ここに少し情報が欠けているように感じます... TransactionScope
を使用してコードを囲むことで、BeginTransaction()
および_RollbackTransaction(
_)呼び出しを本当に置き換えることができますか?
そうでない場合、TransactionScope
はトランザクションをロールバックするためにどのように機能しますか?
基本的に、TransactionScopeはアダプターを追跡しません。データベース接続を追跡します。 DB接続を開くと、接続はアンビエントトランザクション(トランザクションスコープ)が存在するかどうかを確認し、存在する場合は参加します。同じSQLサーバーへの接続が複数ある場合、これは分散トランザクションにエスカレートします。
Usingブロックを使用しているため、例外が発生してもdisposeが呼び出されるようになります。したがって、txScope.Complete()の前にdisposeが呼び出されると、TransactionScopeは接続にトランザクション(またはDTC)をロールバックするように指示します。
TransactionScope
class は、スレッド固有の Transaction
class と連携します。
TransactionScope
が作成されると、スレッドにTransaction
があるかどうかを確認します。存在する場合はそれを使用し、存在しない場合は新しいものを作成してスタックにプッシュします。
既存のものを使用する場合は、リリースのためにカウンターをインクリメントするだけです(その上で Dispose
を呼び出す必要があるため)。前回のリリースでは、Transaction
がコミットされていなかった場合、すべての作業がロールバックされます。
クラスがトランザクションについて魔法のように知っているように見える理由については、このモデルを使用したいクラスの実装の詳細として残されています。
deptAdapter
およびemptAdapter
インスタンスを作成すると、スレッドに現在のトランザクションがあるかどうかがチェックされます(静的 Current
プロパティ on Transaction
クラス)。存在する場合は、Transaction
に自身を登録して、コミット/ロールバックシーケンス(Transaction
が制御し、カーネル、分散、等。)。