RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Performing Transactions in Windows Workflow : Page 3

A transaction-oriented application is one of the common things that developers are tasked with handling, but that doesn't mean it's easy. Transactions are tricky thanks to tricky rollback conditions that must execute flawlessly. Find out why Windows Workflow can take the pain out of building transactions with a visual roadmap.

Testing the Workflow
Time to test the workflow! Press F5 in Visual Studio 2005 to debug the workflow. If everything is coded properly, you should see the output shown in Figure 10.

As expected, $100 is debited from account 12345 and credited into account 54321. Hence the balance of account 12345 is $400 and $200 for account 54321.

What happens if there is an error in one of the code activities? Let's assume that DebitAccount works correctly but there is a runtime error in CreditAccount. To see what happens, make the following changes to the SQL statement in CreditAccount (see the boldface type):

    Private Sub CreditAccount_ExecuteCode( _
       ByVal sender As System.Object, _
       ByVal e As System.EventArgs)
        Dim conn As New SqlConnection(My.Settings.ConnectionString)
        Dim command As New SqlCommand("UPDATE Act SET Balance = Balance + 100 WHERE UserID='54321'", conn)
        Console.WriteLine("---Account credited into 54321---")
    End Sub
Instead of updating the Accounts table, I have changed it to Act, which will result in a runtime error (the table name cannot be found in the database). Press F5 to start the workflow. Visual Studio 2005 will proceed to debit $100 from account 12345, and then when it is time to credit account 54321, it halts due to a runtime error. So, what is the balance of both accounts now? After the debit process, the balance of account 12345 should be $300, but since the crediting part is not performed, the balance of account 12345 would be rolled back to its original balance of $400. This can be verified by checking the value of the Accounts table in Visual Studio 2005.

Hence, activities inside a TransactionScope activity automatically participate in a transaction.

Throwing Exceptions
In the last section, you saw how two activities engaged in a transaction. In the example above, as long as one of the code activities fails to perform correctly, the transaction rolls back. But how do you explicitly define conditions that will initiate a rollback? For example, if account 12345 has a balance of $0, it is clearly not possible to debit the account and hence the transaction must be rolled back.

To show you how this can be done in Windows workflow, make the following changes to your workflow.

  • Add an IfElse activity after DebitAccount (and before CreditAccount).
  • Remove the right branch of the IfElse activity.
  • Add a Throw activity into the left branch of the IfElse activity.
Figure 11 outlines the above steps.

Figure 10. Output of the workflow is shown.
Figure 11. Modifying the workflow to include an IfElse activity.

Select throwActivity and click the "…" button next to the FaultType property in the Properties window. In the Type name text box, enter System.Exception and click OK (see Figure 12). Basically, the Throw activity models the throwing of an exception.

You also need to configure IfElseBranchActivity. Select the activity and set the properties as shown in Figure 13.

Figure 12. Select a .NET Type for throwing an exception.
Figure 13. Configure the properties of the ifElseBranchActivity activity.

The InsuffifientFunds condition (subroutine) will determine if there is a need to throw an exception. In this case, if the balance for account 12345 is less then 0 after the debiting, a throw activity must be invoked. This is accomplished by the following code:

    Private Sub InsufficientFunds( _
       ByVal sender As System.Object, _
       ByVal e As System.Workflow.Activities.ConditionalEventArgs)

        Dim conn As New SqlConnection(My.Settings.ConnectionString)
        Dim command As New SqlCommand("SELECT Balance FROM Accounts WHERE UserID='12345'", conn)

        Dim balance As Double = CDbl(command.ExecuteScalar())
        If balance < 0 Then
            e.Result = True
            e.Result = False
        End If
    End Sub
At the bottom of Workflow1.vb, click the third tab to switch to the Fault Handler view (see Figure 14).

Drag and drop a FaultHandler activity into the position labeled "Drop FaultHandlerActivity Here." Then, drop a Code activity into faultHandlerActivity1 and name it "ExceptionHandler". Figure 15 outlines the steps.

Figure 14. Switch to the Fault Handler view for the workflow by selecting the third tab.
Figure 15. Modify the Fault Handler view of the workflow.

Set the FaultType property of faultHandlerActivity1 to "System.Exception" (you need to click on the "…" button to select the System.Exception type; same as the previous step).

Double-click on ExceptionHandler to switch to its code-behind. Code the following:

    Private Sub ExceptionHandler_ExecuteCode( _
       ByVal sender As System.Object, _
       ByVal e As System.EventArgs)
        Console.WriteLine("---Rolling back the transaction...---")
    End Sub
With that completed, you've now successfully modified the application to throw an exception and roll back the transaction when the account to be debited has insufficient funds.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date