Integrating Enterprise Services Transactional Components

Windows Communication Foundation (WCF) provides an automatic mechanism for integrating with Enterprise Services (see Integrating with COM+ Applications). However, you may want the flexibility to develop services that internally use transactional components hosted within Enterprise Services. Because the WCF Transactions feature is built on the System.Transactions infrastructure, the process for integrating Enterprise Services with WCF is identical to that for specifying interoperability between System.Transactions and Enterprise Services, as outlined in Interoperability with Enterprise Services and COM+ Transactions.

To provide the desired level of interoperability between the incoming flowed transaction and the COM+ context transaction, the service implementation must create a TransactionScope instance and use the appropriate value from the EnterpriseServicesInteropOption enumeration.

Integrating Enterprise Services with a Service Operation

The following code demonstrates an operation, with Allowed transaction flow, that creates a TransactionScope with the Full option. The following conditions apply in this scenario:

  • If the client flows a transaction, the operation, including the call to the Enterprise Services component, is executed within the scope of that transaction. Using Full ensures that the transaction is synchronized with the System.EnterpriseServices context, which means that the ambient transaction for System.Transactions and the System.EnterpriseServices is the same.

  • If the client does not flow a transaction, setting TransactionScopeRequired to true creates a new transaction scope for the operation. Similarly, using Full ensures that the operation’s transaction is the same as the transaction used inside the System.EnterpriseServices component's context.

Any additional method calls also occur within the scope of the same operation’s transaction.

[ServiceContract()]  
public interface ICustomerServiceContract  
{  
   [OperationContract]  
   [TransactionFlow(TransactionFlowOption.Allowed)]  
   void UpdateCustomerNameOperation(int customerID, string newCustomerName);  
}  
  
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]  
public class CustomerService : ICustomerServiceContract  
{  
   [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]  
   public void UpdateCustomerNameOperation(int customerID, string newCustomerName)  
   {  
   // Create a transaction scope with full ES interop  
      using (TransactionScope ts = new TransactionScope(  
                     TransactionScopeOption.Required,  
                     new TransactionOptions(),  
                     EnterpriseServicesInteropOption.Full))  
      {  
         // Create an Enterprise Services component  
         // Call UpdateCustomer method on an Enterprise Services
         // component
  
         // Call UpdateOtherCustomerData method on an Enterprise
         // Services component
         ts.Complete();  
      }  
  
      // Do UpdateAdditionalData on an non-Enterprise Services  
      // component  
   }  
}  

If no synchronization is required between an operation’s current transaction and calls to transactional Enterprise Services components, then use the None option when instantiating the TransactionScope instance.

Integrating Enterprise Services with a Client

The following code demonstrates client code using a TransactionScope instance with the Full setting. In this scenario, calls to service operations that support transaction flow occur within the scope of the same transaction as the calls to Enterprise Services components.

static void Main()  
{  
    // Create a client  
    CalculatorClient client = new CalculatorClient();  
  
    // Create a transaction scope with full ES interop  
    using (TransactionScope ts = new TransactionScope(  
          TransactionScopeOption.Required,  
          new TransactionOptions(),  
          EnterpriseServicesInteropOption.Full))  
    {  
        // Call Add calculator service operation  
  
        // Create an Enterprise Services component  
  
        // Call UpdateCustomer method on an Enterprise Services
        // component
  
        ts.Complete();  
    }  
  
    // Closing the client gracefully closes the connection and
    // cleans up resources  
    client.Close();  
}  

See also