処分される保証はありません。のDispose(bool)
メソッドはSqlTransaction
、実際には条件付きでロールバックします。
// System.Data.SqlClient.SqlTransaction
protected override void Dispose(bool disposing)
{
if (disposing)
{
SNIHandle target = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
target = SqlInternalConnection.GetBestEffortCleanupTarget(this._connection);
if (!this.IsZombied && !this.IsYukonPartialZombie)
{
this._internalTransaction.Dispose();
}
}
catch (OutOfMemoryException e)
{
this._connection.Abort(e);
throw;
}
catch (StackOverflowException e2)
{
this._connection.Abort(e2);
throw;
}
catch (ThreadAbortException e3)
{
this._connection.Abort(e3);
SqlInternalConnection.BestEffortCleanup(target);
throw;
}
}
base.Dispose(disposing);
}
this._internalTransaction.Dispose();
気がつけば、それは呼び出された場合にのみ発生します。ここでの問題はGetBestEffortCleanupTarget
、例外がスローされた場合にクリーンアップされないことです。
あなたの場合、既に述べたように例外がスローされない限り、存在のカテゴリに分類されるZombied
ため、実際にRollback
呼び出しで呼び出しを発行し_internalTransaction.Dispose()
ます。
最後に、これが呼び出されfalse
た場合、ほとんどの場合、破棄されません。
さて、ここで本当に何かが欠けていない限り、このコードがどれほど脆弱であるかに少しぞっとします。
興味深いことに、MSDN のドキュメントは、メソッドについて次のように述べているため、実際には間違っていると思います。Rollback()
トランザクションは、保留状態からのみロールバックできます (BeginTransaction が呼び出された後、Commit が呼び出される前)。Commit または Rollback が呼び出される前に破棄された場合、トランザクションはロールバックされます。