简体   繁体   中英

Two functions queries in one transaction

Have two functions which are used for application purposes where they are consume many times. Currently there is purpose to use them as one within one transaction but i am not sure if i can put them in the way as below. Take look below on them:

First one:

 Public Function Delete(varId As Integer) As Boolean
        Dim result As Boolean = False
        Using con As New SqlConnection(strcon)
            Using cmd As New SqlCommand("DELETE FROM T_Variation WHERE Id=@Id", con)
                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@Id", varId)
                con.Open()
                Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
                con.Close()
                result = True
            End Using
        End Using
        Return result
    End Function

Second one:

  Public Function DeleteAllWhereVarId(pVarId As Integer) As Boolean
        Dim result As Boolean = False
        Using con As New SqlConnection(strcon)
            Using cmd As New SqlCommand("DELETE FROM T_Variation_Attribute WHERE FK_Variation_ID=@FK_Variation_ID", con)
                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@FK_Variation_ID", pVarId)
                con.Open()
                Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
                con.Close()
                result = True
            End Using
        End Using
        Return result
    End Function

Both to transaction:

Now i would like to make function with transaction and use above functions as one. The problem is both first and second function already open their own connection, and here has to be only one if am not mistaken. This is what i don't know how to do.

Public Function DeleteWithAttributes(varId As Integer) As Boolean
Dim result as Boolean = true
Using connection As New SqlConnection(strcon)
      '-- Open generall connection for all the queries
      connection.Open()
      '-- Make the transaction.
      Dim transaction As SqlTransaction
      transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted)

      Try
         Call New DALVariation_Attribute().DeleteAllWhereVarId(varId)
         Delete(varId)

         transaction.Commit()
      Catch ex As Exception
         result = False
         '-- Roll the transaction back.
          transaction.Rollback()
      End Try
End Using

Return result
End Function

You could add an optional parameter that is passed only when the method is called from the transactional code. This parameter is the connection opened before calling the two methods. In this scenario you need to remove the using around the connection and dispose it only if the call comes from non transactional code.

 Public Function Delete(varId As Integer, Optional externalCon as SqlConnection = Nothing) As Boolean
    Dim result As Boolean = False
    Dim localCon as SqlConnection
    Try
        ' if there is no external connection then create one locally 
        if externalCon Is Nothing Then 
           localCon = new SqlConnection(strcon)
           localCon.Open()
        else
           ' use the external passed connection
           localCon = externalCon         
        End if
        Using cmd As New SqlCommand("DELETE FROM T_Variation WHERE Id=@Id", localCon)
            cmd.Parameters.AddWithValue("@Id", varId)
            Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
            result = True
        End Using
    Finally
        ' if we have created the connection dispose/close it
        if externalCon Is Nothing Then
           localCon.Dispose()
        End if
    End Try            
    Return result
End Function

Of course the transactional code could now supply its connection to the Delete method while the other parts of your code ignore it.

 Call New DALVariation_Attribute().DeleteAllWhereVarId(varId, connection)
 Delete(varId, connection)
 transaction.Commit()

You could also look at the TransactionScope class that could allow you to leave your code as it is now

Public Function DeleteWithAttributes(varId As Integer) As Boolean
    Dim result as Boolean = true
    Using scope As New TransactionScope()
    Using connection As New SqlConnection(strcon)
       connection.Open()
       Try
          Call New DALVariation_Attribute().DeleteAllWhereVarId(varId)
          Delete(varId)
          scope.Complete()
       Catch ex As Exception
          result = False
       End Try
    End Using
    ' if you reach this using without calling scope.Complete 
    'the transaction is automatically aborted
    End Using 
    Return result
End Function

However please read also TransactionScope automatically escalating to MSDTC on some machines?

I have never tried this but I have read that TransactionScope will work over multiple connections. Check out this article: https://msdn.microsoft.com/en-us/library/ee818746(v=vs.110).aspx

Edit: No TransactionScope is different. There is a really good example in the link that actually works over two connections so it should get you well on your way.

You can create overloads for your functions to accept a transaction. Something like:

     Public Function Delete(tran As SqlTransaction, varId As Integer) As Boolean
    Dim result As Boolean = True

    If tran Is Nothing Then
        Using con As New SqlConnection(strcon)
            Using cmd As New SqlCommand("DELETE FROM T_Variation WHERE Id=@Id", con)
                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@Id", varId)

                Try
                    con.Open()
                    Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
                Catch 
                    result = False
                End Try
            End Using
        End Using

    Else
        Using cmd As New SqlCommand("DELETE FROM T_Variation WHERE Id=@Id", tran.Connection)
            cmd.Transaction = tran
            cmd.CommandType = CommandType.Text
            cmd.Parameters.AddWithValue("@Id", varId)

            Try
                Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
            Catch 
                result = False
            End Try
        End Using
    End If

    Return result
End Function

    Public Function Delete(varId As Integer) As Boolean
        Return Delete(Nothing, varId)
    End Function

and

Public Function DeleteAllWhereVarId(tran As SqlTransaction, pVarId As Integer) As Boolean
        Dim result As Boolean = True

        If tran Is Nothing Then
            Using con As New SqlConnection(strcon)
                Using cmd As New SqlCommand("DELETE FROM T_Variation_Attribute WHERE FK_Variation_ID=@FK_Variation_ID", con)
                    cmd.CommandType = CommandType.Text
                    cmd.Parameters.AddWithValue("@FK_Variation_ID", pVarId)

                    Try
                        con.Open()
                        Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
                    Catch
                        result = False
                    End Try
                End Using
            End Using
        Else
            Using cmd As New SqlCommand("DELETE FROM T_Variation_Attribute WHERE FK_Variation_ID=@FK_Variation_ID", tran.Connection)
                cmd.Transaction = tran
                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@FK_Variation_ID", pVarId)

                Try
                    Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
                Catch
                    result = False
                End Try
            End Using
        End If

        Return result
    End Function

        Public Function DeleteAllWhereVarId(pVarId As Integer) As Boolean
            Return DeleteAllWhereVarId(Nothing, pVarId)
        End Function

so from the caller routine you can do something like:

Public Sub DoSomeWOrk()
        Using con As New SqlConnection(strcon)
            Dim commit As Boolean = True

            con.Open()
            Dim tran As SqlTransaction = con.BeginTransaction

            If commit Then commit = commit And Delete(tran, 1)
            If commit Then commit = commit And DeleteAllWhereVarId(tran, 1)

            If commit Then
                tran.Commit()
            Else
                tran.Rollback()
            End If
        End Using
    End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM