在 VB.net 和 SQL Server 2008 中开始事务



我以 vb.net 开始交易。我在 SQL Server 2008 上执行存储过程。该存储过程包含BEGIN TRANSACTION .它失败了,ROLLBACK CATCH块运行...

BEGIN CATCH
    IF @@TRANCOUNT > 1 ROLLBACK
        EXEC p_RethrowError
END CATCH

重新投掷有效地做了一个"提高错误"。

执行传递回 vb.net。在"捕获 sqlException" 中执行回滚。

问题:

  • 为什么@@TRANCOUNT是 1 而不是 2?(即为什么不包括 vb.net 中的begin trans

  • 为什么 SQL 中的
  • ROLLBACK也不会回滚客户端转换(但客户端中的回滚会回滚 SQL Server)?

最后,在 vb.net 中,如果您尝试在客户端内回滚事务两次,则会出现异常"事务已完成"。是否知道交易是否已完成或仍在等待中?谢谢。

----------- VB.Net 代码

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

为什么@@TRANCOUNT是 1 而不是 2?(即如何开始反式 不包括 vb.net?

它是2。 这就是它的文档方式,如果不是 2,服务器端ROLLBACK将不会执行。

为什么 SQL 中的回滚也不会回滚客户端传输(但是 客户端中的回滚会回滚 SQL Server)?

没有单独的客户端事务。 它都是相同的服务器端事务,无论当前@@TRANCOUNT值如何,也无论回滚是在何处启动的,ROLLBACK始终回滚。

最后,在 vb.net 中,如果您尝试回滚事务两次 在客户端中,您会收到异常"事务已完成"。

SqlTransaction.Rollback 的实现非常复杂,对于僵尸事务有不同的路径,SQL Server 2005 之前和 SQL Server 2005 之后,例如 2005 之前的原始路径执行简单的Rollback调用,如下所示:

IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION

。并且SqlTransaction客户端对象还会进入僵尸模式,这就是为什么您在随后尝试再次对同一SqlTransaction对象执行ROLLBACK后看到错误的原因。

SQL

Server 2008 上的代码路径类似,只是它不再基于人类可读的 SQL。

这就解释了为什么只有在第二次和后续调用 SqlTransaction.Rollback 时才会出错,即使回滚已经在存储过程中不可撤销地启动。

有吗 无论如何知道交易是否已经完成,或者仍然 待定?

是的。 请参阅此处以获取方法:

获取与事务关联的 SqlConnection 对象,或 null 如果交易不再有效。

因此,如果可以像这样测试:

if (myTransaction.Connection != null) ...

嘿克里斯医生,

诚然,这与你最初的问题没有太大关系。但是,在阅读了您关于如何在 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()

希望这能让你朝着更好的方向开始!

-顺丰

最新更新