Chr*_*ris 5 c# sql transactions using rollback
众所周知,当为SQL Connection,Transaction和Command创建“ using”块时,众所周知,与using块关联的连接,事务或命令在离开using块之后会自行处理。
但是,如果在这些块之一中发生异常,例如在命令块中-事务是否会自行回滚,还是开发人员需要在命令“使用”块内进行try catch,然后添加回滚?尝试在事务处理语句中进行尝试?
只要你没有成功调用Commit,事务就会自动回滚。因此,您的 using 块可能看起来像这样,如果在提交之前引发异常,则事务将回滚。
using (IDbConnection connection = ...)
{
connection.Open();
using (IDbTransaction transaction = connection.BeginTransaction())
{
using (IDbCommand command = ...)
{
command.Connection = connection;
command.Transaction = transaction;
...
}
...
transaction.Commit();
}
}
Run Code Online (Sandbox Code Playgroud)
不保证会被处置。该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);
}
Run Code Online (Sandbox Code Playgroud)
如果您注意到的话,只有在this._internalTransaction.Dispose();接到电话时才会发生这种情况。这里的问题是,如果GetBestEffortCleanupTarget抛出异常,它不会被清理。
在您的情况下,只要没有像已经声明的那样抛出异常,您就会落入存在类别Zombied,因此它实际上会Rollback在_internalTransaction.Dispose()调用中发出调用。
最后,如果调用它,false它肯定不会被释放。
现在,除非我真的遗漏了一些东西,否则我对这段代码的脆弱程度感到有点震惊。
一个有趣的注释是,我认为 MSDN 文档实际上是错误的,因为它对于该Rollback()方法指出:
事务只能从挂起状态回滚(在调用 BeginTransaction 之后,但在调用 Commit 之前)。如果在调用 Commit 或 Rollback 之前处理事务,则事务将回滚。
| 归档时间: |
|
| 查看次数: |
3269 次 |
| 最近记录: |