Friday, 26 October 2012

WCF supports transactions?


Yes, WCF(Windows Communication Foundation) builds WSE/web service extensions as their bindings
binding is a communication way: between client and service.
which done through transaction supported bindings.

we have many bindings

BasicHttpBinding

WSHttpBinding
NetTcpBinding

msmqnetbinding......these are classes in .net framework.

wshttpbinding,nettcpbinding,..ect so first we must know what bindings supports the transactions.

basichttpbinding not supports transactions.

better to choose wshttpbinding.(introbility with old .asmx).
nettcpbinding(best performance).

namespace WcfTransactionsDemos
{
    [ServiceContract]
    public interface IService1
    {
       [OperationContract]
       [TransactionFlow (TransactionFlowOption.Allowed)]
       void Transfer (string accountFrom,string accountTo, double amount);
    }
}
Service Implementation
[ServiceBehavior]
    public class Service1 : IService1
    {

      static  SqlConnection conn = new SqlConnection("uid=sa;pwd=zolt123$;database=wcfdb");

        [OperationBehavior(TransactionScopeRequired = true)]
        public void Transfer(string accountFrom, string accountTo, double amount)
        {           
          Transaction originalTransaction = Transaction.Current;
          CommittableTransaction transaction = new CommittableTransaction ();
          try
          {
              Transaction.Current = transaction;
              Withdraw (accountFrom, amount);
              Deposite (accountTo, amount);
              transaction.Commit ();
             
         }
          catch (Exception ex)
          {
             
              //Transaction.Current = transaction;
              transaction.Rollback();
          
         }
         finally
         {
              Transaction.Current = originalTransaction;
               transaction.Dispose ();
          }

        }
          void Deposite ( string accountId, double deptamount)
         {
             SqlCommand cmd = new SqlCommand();
             cmd.Connection = conn;
             cmd.CommandText = "P_DEPOSIT";
             cmd.CommandType = CommandType.StoredProcedure;
             SqlParameter id = new SqlParameter("@atid",accountId);
         
             cmd.Parameters.Add(id);

             SqlParameter amount = new SqlParameter("@amount",deptamount);          
             cmd.Parameters.Add(amount);
             cmd.ExecuteNonQuery();
             conn.Close();
            
            
        }
          void Withdraw(string accountid, double withamount)
          {

              SqlCommand cmd = new SqlCommand();
              cmd.Connection = conn;
              cmd.CommandType = CommandType.StoredProcedure;
              cmd.CommandText = "P_WITHDRAW";

              SqlParameter id = new SqlParameter("@atid", accountid);             
              cmd.Parameters.Add(id);

              SqlParameter amount = new SqlParameter("@amount",withamount);          
              cmd.Parameters.Add(amount);
              conn.Open();
              cmd.ExecuteNonQuery();

          }
          private static double GetBalance(string accountId)
          {
              double amount = 0;
              SqlCommand cmd = new SqlCommand();
              cmd.Connection = conn;
              cmd.CommandType = CommandType.StoredProcedure;
              cmd.CommandText = "P_GET_BALANCE_BY_ID";

              SqlParameter id = new SqlParameter("@atid",accountId);
          
              cmd.Parameters.Add(id);

              SqlDataReader dr = cmd.ExecuteReader();
              while (dr.Read()==true)
              {
                   amount=Convert.ToDouble(dr[0].ToString());
                 
              }
              return amount;

           
         
          }
    }
Stored Procedures:
P_WITHDRAW

    ALTER  Procedure [dbo].[P_WITHDRAW]
(
        @atid  VARCHAR (50),
        @amount money)
     AS
     IF  NOT  EXISTS ( SELECT * FROM [dbo].[T_ACCOUNT] WHERE accounid = @atid)
        BEGIN
            RAISERROR ( 'Account ID does not exist' , 16,1)
           RETURN
      END   
  IF  NOT  EXISTS ( SELECT * FROM [dbo]. [T_ACCOUNT] WHERE accounid = @atid AND BALANCE> @amount)
      BEGIN
          RAISERROR ( 'insufficient balance' , 16,1)
           RETURN
        END
   
 UPDATE [dbo].[T_ACCOUNT] SET Balance = Balance - @amount WHERE accounid = @atid
dbo.P_DEPOSIT
  ALTER  Procedure [dbo].[P_DEPOSIT]
      (
        @atid         VARCHAR(50),
         @amount FLOAT
    )
 AS
 IF  NOT  EXISTS ( SELECT * FROM [dbo].[T_ACCOUNT] WHERE accounid =@atid)
     BEGIN
        RAISERROR ( 'Account ID does not exist' , 16,1)
      END
 UPDATE [dbo].[T_ACCOUNT] SET Balance = Balance + @amount WHERE accounid =@atid

Table
CREATE TABLE [dbo].[T_ACCOUNT](
      [accounid] [int] IDENTITY(1,1) NOT NULL,
      [NAME] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      [Balance] [money] NULL,
 CONSTRAINT [PK__T_ACCOUNT__47DBAE45] PRIMARY KEY CLUSTERED
(
      [accounid] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Using WCF Test Cleint


Transactions in wcf:




at database


select * from dbo.T_ACCOUNT


1 anand 21000.00
2 balu 9000.00













No comments:

Post a Comment