Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Passing WCF Transactions to COM+

4.89/5 (2 votes)
28 Aug 2012CPOL4 min read 19.9K   165  
This article provides a program to demonstrate how to pass WCF transactions to COM+.

Introduction

A lot of business logic runs in COM+ classes. There is increasingly a need to expose this logic in WCF services. When WCF services are configured as web services, any client may access them. WCF services may run in transactions. When a WCF service calls a COM+ method, this method should run in the same transaction in which the WCF service runs. This program shows how to do this, as there is little documentation on this subject.

Background

COM+

COM+ functionality in .NET is available under the System.EnterpriseServices namespace. Any class that inherits the ServicedComponent class runs in COM+. If in addition, the class has the attribute Transaction(TransactionOption.Required) defined, the methods of this class run in a transaction.

WCF

WCF functionality in .NET is available under the System.ServiceModel namespace. A WCF service is implemented by the ServiceHost class. This class takes as argument in the constructor the class that implements the methods of the service. The methods that have the attribute OperationBehavior(TransactionScopeRequired:=True) run in a transaction.

Calling COM+ from WCF

A WCF service may instantiate a COM+ class and call a method of that class. However, the COM+ method will run in a new transaction. In order for the COM+ method to run in the same transaction, the transaction scope's InteropOption must be set to Full:

VB
Using s As New TransactionScope(Transaction.Current, _
           New TimeSpan(0, 1, 0), EnterpriseServicesInteropOption.Full)
    'Call COM+
End Using

Using the Code

This program is a modified version of the Service Transaction Behavior sample of Microsoft's MSDN/Windows Communication Foundation Samples/Basic/Services/Transaction. The difference is that the data access layer resides in the additional COM+ class, rather in the service. The solution contains four projects:

VB
Dim client As New Tests.PX.CalculatorClient()
Using tx As New TransactionScope()
    client.Add(100)
    ...
    tx.Complete()
End Using
client.Close()
  1. Tests.BE: contains the business entities, in this case, only the typed dataset LogData. The post build events register the assembly in GAC.
  2. Tests.DA: data-access layer that provides methods to retrieve and update records in a database. The post build events register the assembly in GAC and COM+ and copy the config file to the respective GAC folder. The connection string is defined in the app.config file. The assembly contains the following classes:
    1. ClassBase: class running in COM+, providing functions to read data from the database and execute SQL statements.
    2. ClassU: class running in COM+, uses or creates a transaction and provides a function to update a table with the changes recorded in a dataset.
  3. Tests.WS: implements the WCF service, and contains the following classes:
    VB.NET
    <OperationContract()><TransactionFlow_
    (TransactionFlowOption.Mandatory)>Function Add(ByVal n As Double) As Double
    VB
    <OperationBehavior(TransactionScopeRequired:=True, TransactionAutoComplete:=True)> _
    Public Function Add(ByVal n As Double) As Double Implements ICalculator.Add
        Using s As New TransactionScope(Transaction.Current, _
                   New TimeSpan(0, 1, 0), EnterpriseServicesInteropOption.Full)
            RecordToLog([String].Format(CultureInfo.CurrentCulture, _
                        "Adding {0} to {1}", n, runningTotal))
            runningTotal = runningTotal + n
            s.Complete()
        End Using
        Return runningTotal
    End Function
    C#
    host = New ServiceHost(GetType(CalculatorService))
    1. ICalculator: interface defining service methods. Example:
    2. CalculatorService: implementation of the service methods. Each method does a calculator operation, and writes a record to the Log table of the database. Example:
    3. Program: contains the code to start the service:
  4. Tests.UI: Contains a Windows form to test the services. The form provides the button Test WS, which initiates a WCF transaction, calls sequentially the four methods of the service, and if successful, marks the transaction as completed.

To run the program, follow these steps:

VB
Throw New Exception("Ex1")
  1. With Visual Studio 2010, open solution Tests.WCFTrans.sln.
  2. Set the connection string in app.config. It must be a valid connection string to a database, on which you have the right to create tables.
  3. Build the solution. If it fails, check that the paths to gacutil and regsvcs in the post-build events are correct.
  4. You may look in Component Services (Start/Run/comexp.msc) that the COM+ application Tests.DA has been created.
  5. Start the WCF service by double-clicking on Tests.WS\bin\Tests.WS.exe. This will open a command window like the following:

    Service command window

  6. Start Tests.UI either in the debugger, or with the executable Tests.UI\Debug\bin\Tests.UI.exe. The following form appears:

    Test form

  7. Choose the menu item File/Recreate tables. This will create the tables, Log and Log_Audit on the database.
  8. Press the button Test WS. This will initiate a transaction, call the four methods of the service, and complete the transaction. If successful, the following will be displayed:

    Test form after successful run.

  9. To check that the data was written to the database, issue the command: SELECT * FROM Log on the database.
  10. Stop the service by pressing Enter in the command window mentioned before.
  11. To check that no data is saved when an error occurs in the service, add the following code in the Divide method of the class CalculatorService before the statement s.Complete():
  12. Recompile Tests.WS, and start it as before.
  13. In the form of Tests.UI, click the button Test WS again. An error message will appear.
  14. Check that no data was written to the database as before with the same SQL command. The reason is that although the service methods, Add, Delete, and Multiply are completed successfully and written to the database, the service method Divide fails. The transaction is aborted and the changes in the database are rolled back.
  15. You may throw an exception in COM+, as well as in the UI, and the data is rolled back.

History

  1. WCF service CalculatorService uses COM+. UI initiates transaction and calls the service.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)