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