Table of contents
Introduction and goal
This is my fifth WCF FAQ article. This article is completely dedicated to WCF transactions. In this article, we will understand the WCF transaction protocol, the two phases in WCF transactions, transaction options, and finally simple samples for WCF transactions.
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 the basic concepts of WCF like End Points, contracts, and bindings. It also discusses the various hosting methodologies of WCF services. The article finally talks about bindings and one way operations in WCF: http://www.codeproject.com/KB/aspnet/WCF.aspx.
- WCF FAQ Part 2: This FAQ covers 10 questions which talk about concepts like duplex contracts, hosting WCF on different protocols, MSMQ bindings, transaction isolation levels, and two way communication. The article finally talks about two queues: volatile and dead letter queue. http://www.codeproject.com/KB/aspnet/WCFPart2.aspx.
- 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 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: WCFFAQPart3.aspx. - WCF Tracing FAQ Part 4: In this article, we will look at how we can trace and debug information in WCF services. There are some ready made trace listeners provided by WCF. The base of these ready-made trace listeners is the .NET trace listener. So we will first understand the basic concept of trace listener and then go through the ready made trace listeners provided by WCF: WCFTracingFAQ.aspx.
Which protocol is used to handle transactions in WCF?
WCF follows WS-* specifications. So it uses the WS-Atomic protocol to manage transactions 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 the WS-Atomic protocol is that in one transaction you can have heterogeneous WCF services developed in different platforms. 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 two phase commit. So there are two phases: the prepare phase and 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 the 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?
The transaction manager resides at the client computer which initiates the transaction.
Can you explain in depth how the prepare and commit phases work?
Let’s consider three computers as shown in the below figure. The client consuming the WCF service resides in computer A while computers B and C have the WCF services. The transaction is initiated from the computer A. So as we said previously, there are two phases: the prepare phase and the commit phase. In prepare phase, computer A sends messages to all 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. 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 sections, WCF transactions are two-phase commits. In other words, for every commit, you need to get a confirmation response saying if the commit is successful. In one-way WCF services, we do not get any response back, so WCF transactions are not possible with one way WCF service calls.
Can we see a simple WCF example of transactions using a SQL Server database?
To enable a WCF transaction is a six step procedure. So let’s create two WCF services and let’s try to call them in one transaction.
Step 1: Create two WCF services
The first step is to create two WCF service projects which will participate in a 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 the name WCFTransactions
which will consume both the services in one transaction scope.
Step 2: Attribute interface methods with TransactionFlow
In both the WCF services we will create a method called UpdateData
which will do an insert into the database. So the first thing is to create the interface class with the ServiceContract
attribute and the method UpdateData
with the OperationContract
attribute. In order to enable the transaction in the UpdateData
method, we need to attribute it with TransactionFlow
and we have specified that transactions are allowed for this method using the TransactionFlowOption.Allowed
enum.
[ServiceContract]
public interface IService1
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void UpdateData();
}
Step 3: Attribute the implementation with ‘TransactionScopeRequired’
The third 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 the TransactionScopeRequired
attribute.
[OperationBehavior(TransactionScopeRequired = true)]
public void UpdateData()
{
SqlConnection objConnection = new SqlConnection(strConnection);
objConnection.Open();
SqlCommand objCommand = new SqlCommand("insert into " +
"Customer(CustomerName,CustomerCode) values('sss','sss')",
objConnection);
objCommand.ExecuteNonQuery();
objConnection.Close();
}
Step 4: Enable the transaction flow using the WCF service config file
We also need to enable transactions for wsHttpBinding
by setting the transactionFlow
attribute to true
.
<bindings>
<wsHttpBinding>
<binding name="TransactionalBind" transactionFlow="true"/>
</wsHttpBinding>
</bindings>
In the transaction enabled binding, we need to attach with the end point through which our WCF service is exposed.
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="TransactionalBind" contract="WcfService1.IService1">
Step 5: Call the two services in one transaction
Now that we are done with our server side transaction enablement, it’s time to call the above two services in one transaction. We need to use the TransactionScope
object to group the above two 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.
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
{
try
{
ts.Complete();
}
catch (Exception ex)
{
ts.Dispose();
}
}
Below is the complete code snippet in which we have grouped both the WCF transactions in one scope:
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
{
try
{
ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();
obj.UpdateData();
ServiceReference2.Service1Client obj1 = new ServiceReference2.Service1Client();
obj1.UpdateData();
ts.Complete();
}
catch (Exception ex)
{
ts.Dispose();
}
}
Step 6: Test your transaction work
It’s time to test if the transactions really work. We are calling two services and 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 used TransactionFlowOption
. We can specify transactions in three ways in WCF:
TransactionFlowOption.NotAllowed
This is the default option. Using this option, no transaction will be propagated across the binding. If a client attempts to call the WCF service in a transaction, it will be ignored for this option.
TransactionFlowOption.Allowed
This option specifies that the 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 the client must call the WCF service in a transaction mode. If the WCF service is called without a transaction, a FaultException
will be raised.
Source code
You can find the source code for this article here.
For further reading do watch the below interview preparation videos and step by step video series.