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