WCF FAQ: Part 5 - Transactions

Introduction and Goal

This is my 5th WCF FAQ article. This article is completely dedicated to WCF transactions. In this article we will understand the WCF transaction protocol, two phases in WCF transaction, transaction options and finally end up with simple sample for WCF transaction.
Watch my 500 videos on Azure, WCF, WPF, LINQ, Design patterns, WWF, Silverlight, UML @ http://www.questpond.com/
WCF is new to me I am not in a position to read this article?
If you are completely new to WCF then this article will not suffice, my suggestion would be to go through some of the below articles for basics.
WCF FAQ Part 1 - This is a 20 question FAQ for beginners which explains basic concepts of WCF like End points, contracts, and bindings. It also discusses various hosting methodologies of WCF service. The article finally ends talking about bindings and one ways operations in WCF.
WCF FAQ Part 2 - This FAQ covers 10 questions which talks about concepts like duplex contracts , hosting WCF on different protocols, MSMQ bindings, transaction isolation levels, and two way communication. The article finally ends talking about two queues volatile and dead letter queue.
WCF FAQ Part 3 ( Security FAQ ) - In this article, we will start with transport and message security understanding. We will then see simple code samples of how to implement transport and message security using WsHTTP bindings. We will also see what is the difference between 'BasicHttpBinding' and 'WsHttpBinding' with the help of a simple source code. WCF security is a huge topic by itself, but we are sure with this article you will get a quick start of how to go about WCF security.
WCF Tracing FAQ part 4 - In this article, we will look how we can trace and debug information in WCF services. There are some ready made tracelisteners provided by WCF. The base of these ready made trace listeners is .NET trace listener. So we will first understand the basic concept of trace listener and then go through the ready made tracelisteners provided by WCF.

Which protocol is used to handle transactions in WCF?

WCF follows WS-* specifications. So it uses WS-Atomic protocol to managed transaction across WCF services. So you can have different WCF services hosted on different computers and they all can run under one transaction unit. The best part of WS-Atomic protocol is that in one transaction you can have heterogeneous WCF services developed in different platform. In other words you can have JAVA and .NET web services running under one transaction. WS-* specifications are globally approved standards to create services. 

What are the two different kinds of phases in WCF transactions?

WCF transactions follow 2 phase commit. So there are 2 phases one is the prepare phase and the other is the commit phase. All co-ordination of transactions is done by the transaction manager.
In prepare phase the transaction manager checks whether all entities are prepared to commit. In commit phase the actual commit starts. You can think about prepare phase as a check saying that all entities are ready to commit and in the commit phase we do the actual work.

Where does the transaction manager reside?

Transaction manager resides at the client computer who initiates the transaction.

Can you explain in depth how prepare and commit phases work?

Let's consider 3 computers as shown in the below figure. The client consuming the WCF service resides in computer 'A' while computer 'B' and 'C' have the WCF services. The transaction is initiated from the computer 'A'. So as we said previously there are 2 phase one is the prepare phase and the other commit phase. In prepare phase computer 'A' sends messages to all the WCF services saying, are they ready to commit?. Once all WCF services respond saying that they are ready for commit it starts the second phase i.e. In the second phase the WCF client issues a commit command. All the WCF services start execution and once they are done they revert back saying they have committed. When all the WCF services revert saying they have committed the transaction is marked as successful. 

Can we implement transactions in one-way WCF service calls?

As we have already seen in the previous questions that WCF transactions are 2-phase commits. In other words for every commit you need to get a confirmation response, saying is the commit successful. In one-way WCF services we do not get any response back , so WCF transactions are not possible with 1 way WCF service calls.

Can we see simple WCF example of transactions using SQL Server database?

To enable WCF transaction is a 6 step procedure. So let's create two WCF services and let's try to call them in one transaction.
Step 1 - Create two WCF service
The first step is to create two WCF service projects which will participate in one transaction. In both of these WCF services we will do database transactions and we will try to understand how a WCF transaction unifies them. We have also created a web application with name 'WCFTransactions' which will consume both the service in one transaction scope. 
Step 2 - Attribute interface methods with TransactionFlow
In both the WCF service we will create a method called as 'UpdateData' which will do insert into the database. So the first thing is to create the interface class with 'ServiceContract' attribute and the method 'UpdateData' with 'OperationContract' attribute. In order to enable transaction in 'UpdateData' method we need to attribute it with 'TransactionFlow' and we have specified that transactions are allowed for this method using 'TransactionFlowOption.Allowed' enum.
  1. [ServiceContract]  
  2. public interface IService1  
  3. {  
  4.     [OperationContract]  
  5.     [TransactionFlow(TransactionFlowOption.Allowed)]  
  6.     void UpdateData();      
  7. }  
Step 3 - Attribute the implementation with 'TransactionScopeRequired'
The 3rd step is to attribute the implementation of the WCF services with 'TransactionScopeRequired' as true. Below is the code snippet which has a simple database inserting function i.e. 'UpdateData' which is attributed by 'TransactionScopeRequired' attribute.
  1. [OperationBehavior(TransactionScopeRequired = true)]  
  2. public void UpdateData()  
  3. {  
  4.     SqlConnection objConnection = new SqlConnection(strConnection);  
  5.     objConnection.Open();  
  6.     SqlCommand objCommand = new SqlCommand("insert into Customer(CustomerName,CustomerCode) values('sss','sss')",objConnection);  
  7.     objCommand.ExecuteNonQuery();  
  8.     objConnection.Close();  
  9. }  
Step 4 - Enable transaction flow using WCF service config file
We also need to enable transactions for 'wsHttpBinding' by setting the 'transactionFlow' attribute to true.
  1. <bindings>  
  2.  <wsHttpBinding>  
  3.    <binding name="TransactionalBind" transactionFlow="true"/>  
  4.  </wsHttpBinding>  
  5. </bindings>  
The transaction enabled binding we need to attach with the end point through which our WCF service is exposed.
  1. <endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransactionalBind" contract="WcfService1.IService1">  
Step 5 - Call the 2 services in one transaction
Now that we are done with our server side transaction enablement, it's time to call the above 2 services in 1 transaction. We need to use the 'TransactionScope' object to group the above 2 WCF services in one transaction. To commit all the WCF transactions we call the 'Complete' method of the 'Transactionscope' object. To rollback we need to call the 'Dispose' method.
  1. using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))  
  2. {  
  3.     try  
  4.     {  
  5.         // Call your webservice transactions here  
  6.         ts.Complete();  
  7.     }  
  8.     catch (Exception ex)  
  9.     {  
  10.         ts.Dispose();  
  11.     }  
  12. }  
Below is the complete code snippet in which we have grouped both the WCF transactions in one scope as shown below.
  1. using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))  
  2. {  
  3.     try  
  4.     {  
  5.         ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();  
  6.         obj.UpdateData();  
  7.         ServiceReference2.Service1Client obj1 = new ServiceReference2.Service1Client();  
  8.         obj1.UpdateData();  
  9.         ts.Complete();  
  10.     }  
  11.     catch (Exception ex)  
  12.     {  
  13.         ts.Dispose();  
  14.     }  
  15. }
Step 6 - Test does your transaction work
It's time to test if the transactions really work. We are calling two services both of these services are doing an insert. After the first WCF service call we are forcing an exception. In other words the data insert of the first WCF service should revert back. If you check the database records you will see no records are inserted by the WCF service.

What are the different transaction options?

In the previous code we have use 'TransactionFlowOption'. We can specify transaction in 3 ways in WCF:
  • TransactionFlowOption.NotAllowed
    This is a default option. Using this option no transaction will be propagated across the binding. If any client attempts to call the WCF service in a transaction it will be ignored for this option. 
  • TransactionFlowOption.Allowed
    This option specifies that client can call this WCF service in a transaction. It's not compulsory that the service needs to be called in a transaction. You can call without the transaction also. 

  • TransactionFlowOption.Mandatory
    This option specifies that client must call the WCF service in a transaction mode. If the WCF service is called without transaction, 'FaultException' will be raised.
Source code
You can find the source code from top of this article.