Transactions in WCF

Learn how to implement transaction in WCF service using WCF framework.

Transaction is used to maintain the consistency of data while performing operations. In WCF we can implement transaction by setting “TransactionFlowOption” attribute. This attribute can be set while defining the service.

[TransactionFlow(TransactionFlowOption.Allowed)]

Including this, you have to set “OperationBehavior“ while implementing the service.

[OperationBehavior(TransactionScopeRequired = true)]

To explain transaction, I have created one service and client application. Check the below implementation.

ITransactionService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WCFTransactionService
{
    [ServiceContract]
    public interface ITransactionService
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        void InsertData(int intEmpID, string strEmpName, string strAddress, int intAge);
    }
}


TransactionService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Data.SqlClient;

namespace WCFTransactionService
{
    public class TransactionService : ITransactionService
    {
        [OperationBehavior(TransactionScopeRequired = true)]
        public void InsertData(int intEmpID, string strEmpName, string strAddress, int intAge)
        {
             try
            {
                 //Code to insert data
                string strConString = "Your connection string";
                SqlConnection objCon = new SqlConnection(strConString);
                SqlCommand objCmd = new SqlCommand("insert into tab_Employees(EmpId, EmpName, Address, Age) values(" + intEmpID + ",'" + strEmpName + "', '" + strAddress + "'," + intAge + ") ", objCon);
                 objCon.Open();
                 objCmd.ExecuteNonQuery();
                 objCon.Close();
            }
            catch (Exception Ex)
            {
                throw new FaultException("Insert Failed. Details- " + Ex.Message);
             }
        }
     }
}

You can see, in above code I have set TransactionFlow as “TransactionFlowOption.Allowed” for InsertData() method.
Now the check below configuration for service-

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WCFTransactionService.TransactionService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8732/WCFTransactionService/TransactionService/" />
          </baseAddresses>
        </host>
        <endpoint address="" binding="wsHttpBinding" contract="WCFTransactionService.ITransactionService" bindingConfiguration="TransactionBinding">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
   <!--Binding Configuration-->
    <bindings>
      <wsHttpBinding>
        <binding name ="TransactionBinding" transactionFlow ="true"></binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Here I have set transactionFlow ="true" which is required to support transaction.

Consuming Service

To consume this WCF service, I have created one client application. Check the below code implementation.

frmClient.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Transactions;
using TransactionServiceRef;
using System.Data.SqlClient;

public partial class frmClient : System.Web.UI.Page
{
    protected void btnInsert1_Click(object sender, EventArgs e)
    {
        //Defining Transaction scope
        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
        {
             try
            {
                 //Creating the object of TransactionServiceClient to access the method
                TransactionServiceClient objService = new TransactionServiceClient();
                 //Insert-1
                objService.InsertData(101, "Rajesh", "Prem Nagar", 25);
                 //Insert-2
                objService.InsertData(101, "Mahesh", "Shanti Nagar", 26);
                 //Completing the transaction
               ts.Complete();
            }
            catch (Exception Ex)
             {
                 // Disposing the transaction
                 ts.Dispose();
                 Response.Write("Error- " + Ex.Message);
             }
        }
     }

    protected void btnInsert2_Click(object sender, EventArgs e)
    {
        //Defining Transaction scope
        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
         {

            try
            {
                 //Creating the object of TransactionServiceClient to access the method
                TransactionServiceClient objService = new TransactionServiceClient();
                 //Insert-1
                objService.InsertData(101, "Rajesh", "Prem Nagar", 25);

                //Generating 'Divide by zero' exception. So the above insertion will be roll-backed
                int intA = 0;
                int intB = 100 / intA;

                 //Insert-2
                objService.InsertData(101, "Mahesh", "Shanti Nagar", 26);
                 //Completing the transaction
                ts.Complete();
            }
            catch (Exception Ex)
             {
                 //Disposing the transaction
               ts.Dispose();
                 Response.Write("Error- " + Ex.Message);
             }
        }
     }
}


In above code, I have created the object of “TransactionScope” class which is required to implement transaction.

Note-
Tasks which you want to perform under the control of transaction that should be written under the scope of transaction object.

btnInsert1_Click()- Here I have called InsertData() 2 times, so after the execution of this code 2 records will be inserted into database.

btnInsert2_Click()- To confirm transaction is working or not, I have generated “DivideByZeroException” after the execution of InsertData(), so control will jump to catch block and first insert operation will be rollbacked.

You can download the complete from here-

WCFTransactionService

WCFTransactionClient

By Jitendra Faye   Popularity  (1013 Views)