一. WCF事物编程的关键概念介绍
在WCF的事务模式主要由绑定协议、事务流属性、事务范围属性三部分决定。
1. 支持绑定事物的协议有:netTcpBinding和netNamedPipeBinding;
2. 事物流属性:TransactionFlowAttribute
其事物流选项有
1)TransactionFlowOption.NotAllowed: 不参与任何事务。(默认值)
2)TransactionFlowOption.Allowed:允许参与事务。如果调用方(客户端)和服务Binding启用了事务,则参与。
3)TransactionFlowOption.Mandatory: 强制启用事务。调用方(客户端)和服务 Binding必须启用事务才能调用本服务。
3. 事物范围属性:OperationBehaviorAttriute作用于服务实现方法(Operation/Method)上,设置其事物范围属性TransactionScopeRequired为true。
二.WCF事物编程实现
我们采用转账的例子来实现WCF的事物,既A用户向B用户转账。当B用户端入账失败则事物回滚,A用户账户金额不变。
1. 编写用户存款/取款服务
只是举例,简单理解转账就是两个账户的存款与取款。
1)编写服务接口协议:需要设置事物流特性
2) 编写服务接口协议实现:需要设置事物范围需求为true
3)设置宿主机中的服务发布配置:
关键选择支持事物的协议如:NetTcpBingding、配置绑定的协议支持事物流以及事物传输模式
可以采用VS提供的WCF服务配置编译器设置配置文件
生成后的关键配置如下:
4)宿主机用控制台方式发布服务
5)客户端引用WCF服务,自动生成客户端服务引用配置脚本
生成的配置关键脚本如下:
6)编写客户端代码:编写两个方法,一个是转账成功,一个转账失败
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.IO;
using System.Threading;
using System.Transactions;
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
TransactionService.ITransactionService transcation = new TransactionService.TransactionServiceClient();
bool ret = transcation.InitialUser("killer", "jane");
if (!ret)
{
Console.WriteLine("Inital data is fail");
Console.Read();
return;
}
//成功转账方法:数据库记录正确转账数据
TransferAmountIsSuccess(transcation);
//失败转账方法:数据库回滚为转账前的数据
TransferAmountIsFail(transcation);
Console.Read();
}
//数据库的初始数据有“killer”和“Jane”的账户信息,因此转账成功
static void TransferAmountIsSuccess(TransactionService.ITransactionService transcation)
{
TransactionService.User killer = new TransactionService.User() { Name = "killer" };
bool executeResult = false;
killer = transcation.DepositeAmount(out executeResult, killer, 100);
Console.WriteLine(killer.Name + " deposite 100 yuan,Deposit result is {0} and balance is {1}", executeResult, killer.Balance);
TransactionService.User jane = new TransactionService.User() { Name = "jane"};
using (TransactionScope ts = new TransactionScope())
{
killer = transcation.WithdrawingAmount(out executeResult, killer, 80);
jane = transcation.DepositeAmount(out executeResult, jane, 80);
if (!executeResult)
{
Transaction.Current.Rollback();
Console.WriteLine("Transfer account is fail");
}
else
{
ts.Complete();
Console.WriteLine("Transfer account is success!");
}
};
}
//数据库的初始数据有“killer”账户信息,无“Johny”的账户信息,因此转账失败,killer取款信息将回滚
static void TransferAmountIsFail(TransactionService.ITransactionService transcation)
{
bool executeResult = false;
TransactionService.User killer = new TransactionService.User() { Name = "killer"};
TransactionService.User johny = new TransactionService.User() { Name = "johny"};
using (TransactionScope ts = new TransactionScope())
{
killer = transcation.WithdrawingAmount(out executeResult, killer, 20);
johny = transcation.DepositeAmount(out executeResult, johny, 20);
if (!executeResult)
{
Transaction.Current.Rollback();
Console.WriteLine("Transfer account is fail");
}
else
{
ts.Complete();
Console.WriteLine("Transfer account is success!");
}
};
}
}
}
三. 总结
WCF事物实现其实并不是那么神秘,关键是微软都给我们封装好了,我们只是做些简单的WCF事物流的配置和编码,.net编程就是这么简单。