我在vb.net开始一个交易。我在SQL Server 2008上执行存储过程。该存储过程包含BEGIN TRANSACTION
。它失败了,ROLLBACK
阻止CATCH
阻止...
BEGIN CATCH
IF @@TRANCOUNT > 1 ROLLBACK
EXEC p_RethrowError
END CATCH
莱索罗有效地做了一个“反恐”。
执行传递回vb.net。执行“Catch sqlException”中的回滚。
问题:
为什么@@TRANCOUNT
1而不是2? (即不包括vb.net中的begin trans
如何?)
为什么SQL中的ROLLBACK
也不会回滚客户端转换(但客户端的回滚会回滚SQL Server)?
最后,在vb.net中,如果您尝试在客户端内回滚两次事务,则会出现“事务已完成”的异常。无论如何知道交易是否已经完成,或者仍在等待处理?感谢。
----------- VB.Net Code
Public Sub sub1(ByVal intID As Integer, ByVal intValue as integer, ByVal intAuditUser As Int16)
Dim objConn As New SqlConnection(GetDBaseConnectionString())
objConn.Open()
'***** start the transaction ************************************************'
Dim objTrans As SqlTransaction = objConn.BeginTransaction()
Try
Call sub2(objTrans, intID, intValue, intAuditUser)
'***** commit the transaction ************************************************'
objTrans.Commit()
Catch es As SqlException
objTrans.Rollback()
Throw es
Catch ex As Exception
'***** rollback the transaction ************************************************'
objTrans.Rollback()
Throw ex
Finally
If objConn.State <> ConnectionState.Closed Then objConn.Close()
End Try
End Sub
Private Sub Sub2(ByVal objTrans As SqlTransaction, ByVal intID As Integer, ByVal intValue as integer, ByVal intAuditUser As Int16)
Dim objParams As New List(Of SqlParameter)
SqlHelper.AddInParameter(objParams, "ID", SqlDbType.Int, intID)
SqlHelper.AddInParameter(objParams, "Value", SqlDbType.Int, intValue)
SqlHelper.AddInParameter(objParams, "AuditUser", SqlDbType.SmallInt, intAuditUser)
'* save details'
SqlHelper.ExecuteNonQuery(objTrans, CommandType.StoredProcedure, "p_StoredProc_UpdateSomething", objParams.ToArray)
End Sub
答案 0 :(得分:2)
为什么@@ TRANCOUNT 1而不是2? (即如何开始进入 vb.net不包括在内?)
它是2.它是documented的方式,如果它不是2,服务器端ROLLBACK
将不会执行。
为什么SQL中的ROLLBACK也不会回滚客户端trans(但是a 在客户端回滚确实回滚SQL Server)?
没有单独的客户端交易。无论当前的@@ TRANCOUNT值是什么,无论回滚的启动位置如何,都是相同的服务器端事务和ROLLBACK
始终rolls back事务。
最后,在vb.net中,如果你尝试回滚事务两次 在客户端内,您将获得“事务已完成”的异常。
SqlTransaction.Rollback
的实现非常复杂,僵尸事务,SQL Server 2005之前和SQL Server 2005之后的路径不同,例如原始2005之前的路径执行简单的{{1}这样叫:
Rollback
...并且IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
客户端对象另外进入僵尸模式,这就是您在随后尝试在同一SqlTransaction
对象上执行ROLLBACK
后看到错误的原因再一次。
SQL Server 2008上的代码路径类似,只是它不再基于人类可读的SQL。
这解释了为什么只有在SqlTransaction
的第二次和后续调用时才会收到错误,即使回滚已经在存储过程中不可撤销地启动了。
有吗? 无论如何知道交易是否已经完成,或者是否仍然存在 未决?
是。请参阅here了解方法:
获取与事务关联的SqlConnection对象,或者为null 如果交易不再有效。
如果可以这样测试:
SqlTransaction.Rollback
答案 1 :(得分:0)
嘿医生Chris Chris,
不可否认,这与您的初始问题没有太大关系。但是,在阅读了关于如何在vb.net中开始交易的评论之后。这可能会有所帮助:
Dim sqlUpdate As New StringBuilder 'use this to build your insert/update statements
sqlUpdate.Append("SQLCODE")
Dim cnADO As SqlClient.SqlConnection = yourDataBaseStuff.getConnection("targetServer", cnADO)
Dim trans As SqlTransaction = Nothing
Dim sqlCmdUpdate As New SqlCommand(sqlUpdate.ToString, cnADO)
sqlCmdUpdate.Parameters.AddWithValue("@X", new_x) 'where @X is your stored procedure variable, and new_x is what you would like to pass in
' Build Transaction, associate commands
trans = cnADO.BeginTransaction
cmdLoad.Transaction = trans
cmdLoad.CommandText = "Transaction stuff"
cmdLoad.ExecuteNonQuery()
sqlCmdUpdate.Transaction = trans
sqlCmdUpdate.ExecuteNonQuery()
trans.Commit()
希望能让你从一个更好的方向开始!
-sf