1

请看下面的代码:

Private Sub TransactionExample3()
        Dim objDR As SqlDataReader
        Dim objCommand As SqlCommand, objCommand2 As SqlCommand
        Dim objCon As SqlConnection
        Dim objCon2 As SqlConnection
        Dim id As Integer
        Dim list As List(Of Integer) = New List(Of Integer)
        Try
            _ConString = "Data Source=databaseserver;Initial Catalog=Person;User ID=username;Password=password;MultipleActiveResultSets=True"
            list.Add(1)
            list.Add(2)
            list.Add(3)

            For Each i As Integer In list
                Using trans = New TransactionScope()
                    objCon2 = New SqlConnection(_ConString)
                    objCon2.Open()
                    objCommand2 = New SqlCommand()
                    objCommand2.Connection = objCon2
                    Using objCon2
                        objCommand2.CommandText = "UPDATE Person SET forenames = @forenames WHERE " & _
                            " Reference = @Reference "
                        objCommand2.Parameters.AddWithValue("@forenames", i + 1)
                        objCommand2.Parameters.AddWithValue("@Reference", i)
                        objCommand2.ExecuteNonQuery()
                        objCommand2.Parameters.Clear()
                    End Using
                    trans.Complete()
                End Using
            Next

        Catch ex As Exception
            Throw
        Finally

        End Try

    End Sub

此代码有效,即在每个循环中,更改都提交给数据库。

现在请看下面的代码:

Private Sub TransactionExample3()
        Dim objDR As SqlDataReader
        Dim objCommand As SqlCommand, objCommand2 As SqlCommand
        Dim objCon As SqlConnection
        Dim objCon2 As SqlConnection
        Dim id As Integer
        Try
            _ConString = "Data Source=server;Initial Catalog=Person;User ID=Username;Password=Password;MultipleActiveResultSets=True"
            objCon = New SqlConnection(_ConString)
            objCommand = New SqlCommand("SELECT top 10 * from Person")
            objCommand.Connection = objCon
            objCon.Open()
            objDR = objCommand.ExecuteReader()
            Do While objDR.Read
                objCon2 = New SqlConnection(_ConString)
                objCon2.Open()
                Using trans = New TransactionScope()
                    objCommand2 = New SqlCommand()
                    objCommand2.Connection = objCon
                    Using objCon2
                        objCommand2.CommandText = "UPDATE Person SET forenames = @forenames WHERE " & _
                            " Reference = @Reference "
                        objCommand2.Parameters.AddWithValue("@forenames", objDR("Reference") + 10)
                        objCommand2.Parameters.AddWithValue("@Reference", objDR("Reference"))
                        objCommand2.ExecuteNonQuery()
                        objCommand2.Parameters.Clear()
                    End Using
                End Using
            Loop
            objDR.Close() 'line 16
        Catch ex As Exception
            Throw
        Finally

        End Try

    End Sub

在第二个代码摘录中,范围不完整(scope.complete),但结果仍会在 while 循环的每次迭代中提交到数据库。为什么是这样?

4

1 回答 1

2

在第一个循环中,TransactionScope 的打开是在连接打开之前。在第二个是之后。该连接未在事务中登记,因此每个命令都在不被事务持有的情况下执行。

尝试切换这些行

Do While objDR.Read
    Using trans = New TransactionScope()
       objCon2 = New SqlConnection(_ConString)
       objCon2.Open()
       .....

现在你需要调用 trans.Complete()

Private Sub TransactionExample3()
    Dim objDR As SqlDataReader
    Dim objCommand As SqlCommand, objCommand2 As SqlCommand
    Dim objCon As SqlConnection
    Dim objCon2 As SqlConnection
    Dim id As Integer
    _ConString = "Data Source=server;Initial Catalog=Person;User ID=Username;Password=Password;MultipleActiveResultSets=True"
    Using objCon = New SqlConnection(_ConString)
        objCommand = New SqlCommand("SELECT top 10 * from Person")
        objCommand.Connection = objCon
        objCon.Open()
        objDR = objCommand.ExecuteReader()
        Using trans = New TransactionScope()
        Using objCon2 = New SqlConnection(_ConString)
            objCon2.Open()
            Do While objDR.Read
                objCommand2 = New SqlCommand()
                objCommand2.Connection = objCon
                Using objCon2
                    objCommand2.CommandText = "UPDATE Person SET forenames = @forenames WHERE " & _
                        " Reference = @Reference "
                    objCommand2.Parameters.AddWithValue("@forenames", objDR("Reference") + 10)
                    objCommand2.Parameters.AddWithValue("@Reference", objDR("Reference"))
                    objCommand2.ExecuteNonQuery()
                    objCommand2.Parameters.Clear()
                End Using
            Loop
            objDR.Close() 'line 16
        End Using
        trans.Complete()
        End Using    
    End Using
End Sub

我建议将 Transaction and Connection 打开循环移到循环之外,并在 foreach 循环之后调用 Complete 并销毁连接,如果我正确理解您的代码,您将在每个循环中更新一条记录,因此只有在您想要更新时,Transaction 才有意义您的所有记录或没有。另一个小的优化可能是将 SqlCommand 和参数的创建移到循环之外。您只更新循环内的参数值,而无需在每个循环中破坏和重建参数集合

于 2013-07-29T12:01:28.113 回答