4.WCF事务【Transaction】
契约:
namespace Rhythmk.Contracts
{
[ServiceContract(Namespace="http://wwww.wangkun.com")]
public interface ICalculate
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
void OperationTransaction(int i);
/*
TransactionFlow - 指定服务操作是否愿意接受来自客户端的传入事务
NotAllowed - 禁止事务。默认值
Allowed - 允许事务
Mandatory - 强制事务
*/
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
void OperationTransactionExe(int i);
}
}
服务:
using System.ServiceModel;
using Rhythmk.Contracts;
namespace Rhythmk.Services
{
/// <summary>
/// 计算器
/// </summary>
public class Calculate : ICalculate
{
#region ICalculate 成员
/// OperationBehavior - 指定服务方法的本地执行行为
/// 1、TransactionScopeRequired - 如果方法需要事务范围才能执行,则为 true;否则为 false。默认值为 false
/// 将 TransactionScopeRequired 设置为 true,可以要求操作在事务范围内执行。如果流事务可用,则操作会在该事务内执行。如果流事务不可用,则会创建一个新事务并使用它来执行操作
/// 2、TransactionAutoComplete - 默认值为 true
/// true - 当方法完成执行时,将把该事务标志为完成(自动提交事务)
/// false - 需要调用OperationContext.Current.SetTransactionComplete()方法来手工配置该事务的正确完成;否则,该事务将被标志为失败(手动提交事务)
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void OperationTransaction(int i)
{
string sql = "INSERT INTO TB_TEST (name,txt,addtime) VALUES ( 'OperationTransaction','"+(i*i).ToString()+"',GETDATE())";
SqlHelp.ExcuteSqlServer(sql);
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void OperationTransactionExe(int i)
{
if (i % 10 == 0)
{
throw new Exception("测试事务异常!");
}
string sql = "INSERT INTO TB_TEST (name,txt,addtime) VALUES ( 'OperationTransactionExe','" + (i * i).ToString() + "',GETDATE())";
SqlHelp.ExcuteSqlServer(sql);
}
#endregion
}
}
寄宿
class Program
{
static void Main(string[] args)
{
CreateCalculateService();
}
static void CreateCalculateService()
{
Console.WriteLine("----------CreateCalculateService---Star---------");
using (ServiceHost host = new ServiceHost(typeof(Calculate)))
{
host.Opened += delegate { Console.WriteLine("CalculateService已经启动,按任意键终止服务!"); };
host.Open();
Console.Read();
}
}
}
服务端配置:
备注: <binding name="TransactionConfig" transactionFlow="true"></binding> 需要在配置中开启事务流
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metaBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Rhythmk.Services.Calculate" behaviorConfiguration="metaBehavior" >
<endpoint address=""
binding="wsHttpBinding" bindingConfiguration="TransactionConfig" contract="Rhythmk.Contracts.ICalculate" >
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:1234/Rhythmk.Services.Calculate"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="TransactionConfig" transactionFlow="true"></binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
通过服务引用调用事务:
public void ExcuteTransaction(int i)
{
RhythmWCF.ICalculate proxy = new RhythmWCF.CalculateClient();
System.Transactions.TransactionOptions tran = new System.Transactions.TransactionOptions();
//设置事务超时时间
tran.Timeout = new TimeSpan(3000);
//设置事务的隔离级别
tran.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using (var ts = new System.Transactions.TransactionScope())
{
try
{
proxy.OperationTransaction(i);
// 输入为10的倍数 将会报告异常 .
proxy.OperationTransactionExe(i);
ts.Complete(); //提交事务
}
catch (Exception ex)
{
lb.Text = ex.ToString();
}
}
}
一只站在树上的鸟儿,从来不会害怕树枝会断裂,因为它相信的不是树枝,而是它自己的翅膀。与其每天担心未来,不如努力做好现在。