WCF 分布式事务的使用
来源:互联网 发布:java返回值怎么理解 编辑:程序博客网 时间:2024/05/16 14:50
WCF 支持分布式事务,也就是说事务可以跨越服务、进程、机器边界,在多个服务和客户端间存在.那么在WCF中如何使用分布式事务呢?
下面我们以一个例子来演示在wcf中使用分布式事务。下图是这个demo的整个solution:
为了便于测试,我们在建立一个临时表用于测试。表名为MGender.表中有两个字段:GenderCode,char(1),GenderDesc varchar(20).
在这个solution中WCFTrasactionServcies是contract 和Service。它是一个类库项目,在这里为了方便我们将interfact和实现interfact写在一个cs文件里,当然这种方法是不被推荐的。代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Data.SqlClient;
namespace WCFTrasactionServices
{
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IGenderInsert1
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void insertGerder1(string genderID, string genderDesc);
}
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IGenderInsert2
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void insertGerder2(string genderID, string genderDesc);
}
public class TestService1 : IGenderInsert1
{
#region IGenderInsert1 Members
[OperationBehavior(TransactionScopeRequired = true)]
public void insertGerder1(string genderID, string genderDesc)
{
using (SqlConnection conn = new SqlConnection("Data Source=localhost;DataBase=Test;integrated security=true"))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "insert into MGender (GenderCode,GenderDesc) values (@GenderCode,@GenderDesc)";
cmd.Parameters.Add(new SqlParameter("@GenderCode", genderID));
cmd.Parameters.Add(new SqlParameter("@GenderDesc", genderDesc));
cmd.Connection = conn;
cmd.ExecuteNonQuery();
}
}
#endregion
}
public class TestService2 : IGenderInsert2
{
#region IGenderInsert2 Members
[OperationBehavior(TransactionScopeRequired = true)]
public void insertGerder2(string genderID, string genderDesc)
{
using (SqlConnection conn = new SqlConnection("Data Source=localhost;DataBase=Test;integrated security=true"))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "insert into MGender (GenderCode,GenderDesc) values (@GenderCode,@GenderDesc)";
cmd.Parameters.Add(new SqlParameter("@GenderCode", genderID));
cmd.Parameters.Add(new SqlParameter("@GenderDesc", genderDesc));
cmd.Connection = conn;
cmd.ExecuteNonQuery();
}
}
#endregion
}
}
TransactionFlowAttribute 只能用于服务方法(Operation/Method)上,它允许我们进行不同的事务参与设置。有一点要注意,我们不能为 IsOneWay=true 的服务设置事务支持。
TransactionFlowOption.NotAllowed: 不参与任何事务。(默认值)
TransactionFlowOption.Allowed: 允许参与事务。也就是说,如果调用方(客户端)和服务Binding启用了事务,则参与。
TransactionFlowOption.Mandatory: 强制启用事务。调用方(客户端)和服务 Binding 必须启用事务才能调用本服务。
WCFTrasactionHost是host,为了让WCF支持分布式事务,我们要修改Binding的一些属性。只有 TCP-、 IPC- 以及 WS-related 等 Binding 支持事务。缺省情况下,这些 Binding 并不会参与事务,需要我们显示将 TransactionFlow 属性设置为 true 才行。
我们可以通过配置文件来设置
<netTcpBinding>
<binding name = "Transactional" transactionFlow = "true" />
</netTcpBinding>
</bindings>
tcpBinding.TransactionFlow = true;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCFTrasactionHost
{
class Program
{
static void Main(string[] args)
{
ServiceHost host1 = new ServiceHost(typeof(WCFTrasactionServices.TestService1));
host1.Open();
ServiceHost host2 = new ServiceHost(typeof(WCFTrasactionServices.TestService2));
host2.Open();
Console.WriteLine("endpoint is listenning");
Console.ReadKey();
}
}
}
<configuration>
<system.serviceModel>
<services>
<service name ="WCFTrasactionServices.TestService1" behaviorConfiguration="TestBehavior1">
<endpoint binding="netTcpBinding" bindingConfiguration="TransactionalTCP" contract="WCFTrasactionServices.IGenderInsert1" address="net.tcp://localhost/Test1"></endpoint>
</service>
<service name ="WCFTrasactionServices.TestService2" behaviorConfiguration="TestBehavior2">
<endpoint binding="netTcpBinding" contract="WCFTrasactionServices.IGenderInsert2" bindingConfiguration="TransactionalTCP" address="net.tcp://localhost/Test2"></endpoint>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="TransactionalTCP" transactionFlow="true"></binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="TestBehavior1">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost/Test1"/>
</behavior>
<behavior name="TestBehavior2">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost/Test2"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
WCFTrasactionClient:是client.我们使用svcutil 工具生成客户端代码,生成两个cs文件,TestService1.cs和TestService2.cs,当然我们也可以手工写客户端类。
WCFTrasactionClient代码:
class Program
{
static void Main(string[] args)
{
GenderInsert1Client test1 = new GenderInsert1Client();
GenderInsert2Client test2 = new GenderInsert2Client();
using (TransactionScope scope = new TransactionScope())
{
try
{
test1.insertGerder1("M", "Male");
test2.insertGerder2("F"Female");
scope.Complete();
Console.WriteLine("Client has called the services.");
}
catch
{ //do noting
}
finally
{
//(test1 as IDisposable).Dispose();
//(test2 as IDisposable).Dispose();
}
}
}
这样我们就可以成功的往表MGender中插入两条数据。如果我们修改 :
test1.insertGerder1("M", "Male"); test2.insertGerder2("F"Female");修改为 test1.insertGerder1("M", "Male"); test2.insertGerder2("FF"Female");
这样就会有异常,因为FF是两位字符,而GenderCode是char1型的,所以事务不成功,但第一条数据也成功插入,所以WCF会自动回滚第一插入的数据 test1.insertGerder1("M", "Male");
- WCF 分布式事务的使用
- WCF 使用 WSAtomicTransaction11 分布式事务 Oracle
- WCF 分布式事务-应用
- WCF分布式事务
- WCF 分布式事务-应用
- WCF 分布式事务
- .net remoting的事务传播以及wcf分布式事务
- WCF系列_分布式事务
- WCF分布式事务(EF)
- WCF之分布式事务一
- WCF 使用 Https 绑定数据(包括分布式WCF事务配置方法)
- 分布式事务 dtc 的使用
- WCF系列_分布式事务(上)
- WCF系列_分布式事务(下)
- Spring.Net+WCF实现分布式事务
- WCF系列_分布式事务(上)
- WCF系列_分布式事务(下)
- 使用分布式事务配置MSDTC的步骤
- 实现树的checkbox 选择操作
- 关于阅读源代码
- 一个女孩写给女孩的话-不管是男是女看看吧,看看我们做了里面的多少
- NHibernate学习
- spring框架中添加HibernateInterceptor使得quartz可以调用Hibernate Session
- WCF 分布式事务的使用
- vi 里面没颜色
- 从网页中获取有用的信息 html2text
- 数据库:left join,right join,inner join
- EA1和B2Bi介绍
- 支持VC6.0的SDK包
- 把系统盘制作成ISO映像文件
- arm系统的中断解析
- Hypergraph, Channel Box, KeyFrame