Windows Communication Foundation - SPLessons
SPLessons 5 Steps, 3 Clicks
5 Steps - 3 Clicks

WCF Transactions

WCF Transactions

Implementing transactions in WCF Service.

shape Description

A transaction is a set of queries to be executed as a group with the database.
  • In general, when working with transactions, all the queries should be executed successfully. Then only transactions should be committed to the database.If any single query is not executed successfully then the complete transaction should be rollback.
  • Any transaction must and should satisfy properties called as "ACID" properties.

Atomicity

shape Description

Within the transaction, all the queries of the transaction should be executed. Otherwise, no query should be executed.

Consistency

shape Description

Queries should not create any inconsistency within the database after the execution.

Isolation

shape Description

While multiple transactions are being executed simultaneously, one transaction should not affect the other transaction. And transaction should be able to execute independently as well as after completion of all transactions, all transactions should lead to consistency within the database.

Durability

shape Description

The transaction should not lead to any inconsistency due to a breakdown of the system or power failure etc during the execution of the transaction. When working with transactions with WCF Service, any transaction will contain three phases.
  1. Ready Phase
  2. Execution phase
  3. Commit phase

shape Conceptual figure

Steps:
  1. The client sends a request to WCF Service1 to confirm whether it is ready to implement transaction or not.
  2. WCF Service1 acknowledge to the client, that it is ready to implement to the transaction.
  3. The client sends a request to the WCF Service2 to confirm whether it is ready to implement transaction or not.
  4. WCF Service2 will acknowledge to the client i.e. is ready to implement to the transaction.
  5. The client sends to request to WCF Service1 to execute one or more of the queries of the transaction.
  6. WCF Service1 will execute step 6, this queries to the database.
  7. WCF Service1 will acknowledge to the execution of queries with the client.
  8. The client will send a request to WCF Service2 to execute one or more queries of the transaction.
  9. WCF Service2 will execute these queries with the database.
  10. WCF Service2 will acknowledge the execution of queries with the database.
  11. Then client application will completely transaction by sending a commit request to the database
To implement the transactions with every function within the interface use the transaction flow attribute like [TransactionFloe(TransactionFlowoption.Allowed)] within the service class, the function should be preceded with an attribute known as operation behavior. [OperationBehavior(TransactionscopeRequired=true)]

Implementing Transaction in WCF

shape Description

Here, Transaction is implemented with the database from SQL like Bank Transactions database. Below steps has to be followed while implementation.
  • First create a database with the name as Bank Transaction.
  • In that transaction, create three tables like Customer, Merchant, and Transactions.
  • In customer table, takes two fields like CID, and Cbalance.
  • In Merchant table, you have to take two fields like MID, Cbalancc.
  • In Transaction table, take nine fields like TID, CID, MID, Transactin_Date, Transaction_Amount, Cbal_before_Tra, Cbal_after_Tra, Mbal_before_Tra, and Mbal_after_Tra.
After creating a database with the three tables, now, we create three services like For, each one take one project with the same solution.
  • Customer Transaction service will contain code to update the customer current balance when the transaction is performed.
  • Merchant Transaction service will contain code to update the merchant current balance when a transaction a transaction is performed.
  • Main Transaction service will contain code to insert a new record into a transaction table whenever a transaction is performed.

shape Example

Now creating Customer Transaction: 1. Create a new WCF Service project with the name Customer Transaction. Change the interface file name to IcustomerService.cs. Now go to IcustomerService.cs file and write the following code: [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace CustomerTrasaction { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICustomerService" in both code and config file together. [ServiceContract] public interface ICustomerService { [OperationContract] [TransactionFlow(TransactionFlowOption.Allowed)] void UpdateCustomer(int Id, double Amount); } }[/csharp] Now, add the reference to Service.Transaction namespace and go to CustomerService.cs file and write the following code. [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.Data.SqlClient; using System.Configuration; namespace CustomerTrasaction { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "CustomerService" in code, svc and config file together. public class CustomerService : ICustomerService { // readonly string CONNECTION_STRING = ConfigurationManager.ConnectionStrings["TransactionDB"].ConnectionString; [OperationBehavior(TransactionScopeRequired = true)] public void UpdateCustomer(int Id, double Amount) { try { string sqlcon = "Server=srinu;database=BankTransactions;uid=sa;pwd=Srinu20!"; SqlConnection con = new SqlConnection(sqlcon); string s = "update Customer set CBalance=" + Amount + " where CID='" + Id '"; SqlCommand cmd = new SqlCommand(s, con); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } catch (Exception ex) { throw ex; } } } } [/csharp] 2. Create another WCF service project with the name Merchant Transaction. Change the interface file name to IMerchent.cs and write the following code: [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace MerchantTransaction { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IMerchantService" in both code and config file together. [ServiceContract] public interface IMerchantService { [OperationContract] [TransactionFlow(TransactionFlowOption.Allowed)] void UpdateMerchant(int Id, double Amount); } }[/csharp] Now, add the reference to Service.Transaction namespace and go to MerchentService.cs file and write the following code. [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.Data.SqlClient; namespace MerchantTransaction { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "MerchantService" in code, svc and config file together. public class MerchantService : IMerchantService { [OperationBehavior(TransactionScopeRequired = true)] public void UpdateMerchant(int Id, double Amount) { try { string sqlcon = "Server=srinu;database=BankTransactions;uid=sa;pwd=Srinu20!"; SqlConnection con = new SqlConnection(sqlcon); string s = "update Merchant set CBalance=" + Amount + " where MID='" + Id '"; SqlCommand cmd = new SqlCommand(s, con); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } catch (Exception ex) { throw ex; } } } } [/csharp] Now run the application and check to see whether service is working or not. 3. Create a third WCF Service project with the name as a Main Transaction. Change the interface file to ITransactionService.cs and class file name to TrasactionService.svc. Go to ITrasaction.cs and write the following code. [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace MainTransaction { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ITransactionService" in both code and config file together. [ServiceContract] public interface ITransactionService { [OperationContract] [TransactionFlow(TransactionFlowOption.Allowed)] void InsertTransaction(int id1, int id2, int id3, DateTime d1, double amnt1, double amnt2, double amnt3, double amnt4, double amnt5); } } [/csharp] Go to Transaction.svc file and add a reference to System.Transaction namespace and write the following code: [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.Data.SqlClient; namespace MainTransaction { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "TransactionService" in code, svc and config file together. public class TransactionService : ITransactionService { [TransactionFlow(TransactionFlowOption.Allowed)] public void InsertTransaction(int cid, int mid, int tid, DateTime trandate, double TransactionAmount, double BalBforeTran, double BalAfterTran, double MBalBforeTran, double MBalAfterTran) { try { string sqlcon = "Server=srinu;database=BankTransactions;uid=sa;pwd=Srinu20!5;"; SqlConnection con = new SqlConnection(sqlcon); SqlCommand cmd = new SqlCommand(@"insert into Transactions(TID,CID,MID,Transaction_Date,Transaction_Amount, CBal_Before_Tran,CBal_After_Tran,MBal_Before_Tran,MBal_After_Tran) Values(@tid,@cid,@mid,@trandate,@TransactionAmount,@BalBforeTran,@BalAfterTran,@MBalBforeTran,@MBalAfterTran)", con); cmd.Parameters.AddWithValue("@tid", tid); cmd.Parameters.AddWithValue("@cid", cid); cmd.Parameters.AddWithValue("@mid", mid); cmd.Parameters.AddWithValue("@trandate", trandate); cmd.Parameters.AddWithValue("@TransactionAmount", TransactionAmount); cmd.Parameters.AddWithValue("@BalBforeTran", BalBforeTran); cmd.Parameters.AddWithValue("@BalAfterTran", BalAfterTran); cmd.Parameters.AddWithValue("@MBalBforeTran", MBalBforeTran); cmd.Parameters.AddWithValue("@MBalAfterTran", MBalAfterTran); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } catch (Exception ex) { throw ex; } } // public static object required { get; set; } } } [/csharp] Now run the application and check to see whether service is working or not. Create client application for consuming the services Create a new project with the name as TrasactionWebClient and add the WEB ASP Application. Below screen shows you how to add web application. After creating client application, add service references. Below screen shows how to add service references: After clicking on Add service reference,below screen appears. Below screen shows how to add the service references. Like above screen add all the references. After adding the all the services references, design client interface. To design the user interface, write a code in Default.aspx like below: [csharp] <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TransactionWebClient._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <center> <table> <tr> <td> Enter Transaction Id : </td> <td> <asp:TextBox ID="txtTid" runat="server"></asp:TextBox> </td> </tr> <tr> <td> Enter Customer Id : </td> <td> <asp:TextBox ID="txtcid" runat="server"></asp:TextBox> </td> </tr> <tr> <td> Enter Merchent Id : </td> <td> <asp:TextBox ID="txtmid" runat="server"></asp:TextBox> </td> </tr> <tr> <td> Enter Transaction Amount : </td> <td> <asp:TextBox ID="txttransactionamount" runat="server"></asp:TextBox> </td> </tr> <tr> <td> </td> <td> <asp:Button ID="btnSubmit" Text="Submit" runat="server" OnClick="btnSubmit_Click" /> </td> </tr> <tr> <td colspan="2"> <asp:Label ID="lbldisplay" runat="server"></asp:Label> </td> </tr> </table> </center> </div> </form> </body> </html> [/csharp] After wiring an above code, an interface is obtained like below: Write a code in Default.aspx.cs like below. [csharp]using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.ServiceModel; using System.Data.SqlClient; using System.Transactions; namespace TransactionWebClient { public partial class _Default : System.Web.UI.Page { SqlConnection cn = new SqlConnection("Server=srinu;database=BankTransactions;uid=sa;pwd=Srinu20!5;"); SqlCommand cmd; SqlDataReader dr; SRCustomer.CustomerServiceClient objc = new SRCustomer.CustomerServiceClient(); SRMerchant.MerchantServiceClient objm = new SRMerchant.MerchantServiceClient(); SRTransaction.TransactionServiceClient objt = new SRTransaction.TransactionServiceClient(); protected void Page_Load(object sender, EventArgs e) { } protected void btnSubmit_Click(object sender, EventArgs e) { string s = "select * from Customer where CID='" + txtcid.Text + "'"; cn.Open(); cmd = new SqlCommand(s, cn); dr = cmd.ExecuteReader(); dr.Read(); double custbal1 = Convert.ToDouble(dr[1]); double custbal2 = custbal1 - Convert.ToDouble(txttransactionamount.Text); dr.Close(); if (custbal2 < 0) { lbldisplay.Text = "Insufficient Balance Transaction can not be performed"; } else { try { s = "select * from Merchant where MID='" + txtmid.Text + "' "; cmd = new SqlCommand(s, cn); dr = cmd.ExecuteReader(); dr.Read(); double mbal1 = Convert.ToDouble(dr[1]); double mbal2 = mbal1 + Convert.ToDouble(txttransactionamount.Text); using (TransactionScope Ts = new TransactionScope(TransactionScopeOption.Required)) { objc.UpdateCustomer(Convert.ToInt32(txtcid.Text), custbal2); objm.UpdateMerchant(Convert.ToInt32(txtmid.Text), mbal2); objt.InsertTransaction(Convert.ToInt32(txtTid.Text), Convert.ToInt32(txtcid.Text), Convert.ToInt32(txtmid.Text), DateTime.Now, Convert.ToDouble(txttransactionamount.Text), custbal1, custbal2, mbal1, mbal2); Ts.Complete(); lbldisplay.Text = "Trasanction completed succssfully!!!"; } } catch (Exception ex) { lbldisplay.Text = ex.Message; } cn.Close(); } } } }[/csharp] Write a code on web.config like below: [csharp]</pre> <pre></configuration> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IMerchantService"/> <binding name="WSHttpBinding_ICustomerService"/> <binding name="WSHttpBinding_ITransactionService"/> </wsHttpBinding> </bindings> <client> <endpoint address="http://srinu:91/MerchantService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMerchantService" contract="SRMerchant.IMerchantService" name="WSHttpBinding_IMerchantService"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="http://srinu:90/CustomerService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICustomerService" contract="SRCustomer.ICustomerService" name="WSHttpBinding_ICustomerService"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="http://srinu:92/TransactionService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITransactionService" contract="SRTransaction.ITransactionService" name="WSHttpBinding_ITransactionService"> <identity> <dns value="localhost"/> </identity> </endpoint> </client> </system.serviceModel> <system.web> <compilation debug="true"/></system.web> </configuration> [/csharp] Now run the client application. Below screen is obtained. And, enter the values into above fields and click on Submit button then below screen appears.