Reputation: 15817
Please see the code below:
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
This code works i.e. on each loop the changes are committed to the database.
Now please see the code below:
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
In the second code exherpt, the scope is not complete (scope.complete), however the results are still committed to the database on each iteration of the while loop. Why is this?
Upvotes: 1
Views: 1474
Reputation: 216313
In the first loop the opening of the TransactionScope is before the opening of the connection. In the second one is after. The connection is not enlisted in the Transaction and thus every command executes without being held by a transaction.
Try to switch these lines
Do While objDR.Read
Using trans = New TransactionScope()
objCon2 = New SqlConnection(_ConString)
objCon2.Open()
.....
Now you need the call to 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
I suggest to move the Transaction and Connection opening outside the loop and call the Complete and destroy the connection after the foreach loop, if I understand your code correctly you update one record at each loop and so the Transaction makes sense only if you want to update all of your records or none. Another minor optimization could be to move the creation of the SqlCommand and the Parameters outside the loop. You update just the parameters value inside the loop without destroying and rebuilding the parameter collection at each loop
Upvotes: 2