最近在学WCF,所以有两个设想疑问(菜鸟多疑问):

  • 如果有WCF服务A,WCF服务B,客户端调用WCF服务A插入一条数据,然后再调用服务B也插入一条数据,然而服务B出错了进行了回滚,服务A能不能也进行回滚操作?
  • 或是客户端调用服务A和服务B,成功了插入了两条数据之后,客户端这边出错了,如何让服务A和服务B插入的数据也回滚操作?

经过学习探索,了解到WCF支持分布式事务,事务可以在多个服务中传播,也可以在服务端与客户端之间传播。

注:WCF内并非所有绑定都支持事务的,常用的BasicHttpBinding就不支持事务的传播。只有以下几个绑定才能支持事务流的运转:NetTcpBinding、WSHttpBinding、WSDualHttpBinding、WSFederationHttpBinding、NetNamedPipeBinding。

代码尝试

先建一个WCF服务(WSHttpBinding),有两个Add方法,在客户端两次分开调用

 [ServiceContract]
public interface IService1
{ [OperationContract]
string AddData_1(string a); [OperationContract]
string AddData_2(string a); }
 public class Service1 : IService1
{ [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
public string AddData_1(string b)
{
using (testEntities ts = new testEntities())
{
Student a = new Student()
{
Age = ,
Class = b,
Sex = "男",
Score =
};
ts.Student.Add(a);
ts.SaveChanges();
}
return "";
} [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
public string AddData_2(string b)
{
using (testEntities ts = new testEntities())
{
Student a = new Student()
{
Age = ,
Class = b,
Sex = "男",
Score =
};
ts.Student.Add(a);
ts.SaveChanges();
throw new Exception("出错拉!"); //抛出错误
} return "";
}
}

其中标红解释:

TransactionScopeRequired:值为true时,表示此WCF服务的方法中启动事务,为false,反之不启动。

TransactionAutoComplete:值为true时为隐式事务,方法在运行过程中没有抛出Exception,事务会自动提交。如果期间出现任何异常,事务就会自动回滚;false时,显式事务,必须OperationContext.Current.SetTransactionComplete () 显式提交事务。

TransactionFlowOption:设置为Allowed,开启事务传播,客户端的事务传播到服务端。

        有三个值:

      NotAllowed,禁止客户端传播事务流到服务端,即使客户端启动了事务,该事务也会被忽略;

        Allowed,允许客户端的事务传播到服务端,但服务器端不一定会引用到此事务(如果服务端方法没开启事务);

      Mandatory,服务端与客户端必须同时启动事务流,否则就会抛出InvalidOperationException异常。

web.config配置(重要)

服务端web.config

<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<!--启动事务流-->
<binding name="defaultWSHttpBinding" transactionFlow="true" />  <!--这里一定要设置绑定的transactionFlow为true,否则无法使用事务-->  

</wsHttpBinding>
</bindings> <behaviors>
<serviceBehaviors>
<behavior>
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WcfDemo_shiwu.Service1">
<endpoint address="" binding="wsHttpBinding"
contract="WcfDemo_shiwu.IService1" bindingConfiguration="defaultWSHttpBinding"/>  <!--这里一定要设置bindingConfiguration--> 
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
-->
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>

客户端

<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1" transactionFlow="true" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:5854/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="TestService.IService1"
name="WSHttpBinding_IService1">
<identity>
<userPrincipalName value="DESKTOP-350R9O7\qiuguochao" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>

客户端代码

情况一:WCF服务中的方法2报错回滚,那么之前第一次调用插入的是否成功回滚?

 static void Main(string[] args)
{
//客户端开启分布式事务,要引用System.Transactions.dll
using (TransactionScope ts = new TransactionScope())
{
//调用服务
using (TestService.Service1Client service = new TestService.Service1Client())
{
service.AddData_1(""); }
Console.WriteLine("第一次调用:成功插入一条数据");           //重新去调用WCF服务
using (TestService.Service1Client service2 = new TestService.Service1Client())
{
//WCF中的AddData_2会报错
service2.AddData_2(""); }
ts.Complete();
}
}

结果:

WCF服务插入第二条数据,已经报错,因为该方法中已经设置  [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)],开启了事务,所以第二数据肯定是会被回滚的

且看第一条数据是否也会被回滚?,结果是两条数据都被回滚了

情况2:两次调用WCF服务成功插入数据后,客户端报错回滚,在WCF服务中插入的数据是否也回滚?

将抛出错误注释掉,重新运行WCF服务

改写客户端代码,并设下断点:

执行到断点,查看数据情况

已经成功插入,继续执行,由于没有进行提交,所以该事务将会自动回滚,且看在WCF服务中插入的数据是否会被回滚

客户端进行了回滚操作,很显然,客户端的事务传播的WCF中的方法事务,也将相应的操作回滚。

WCF(三)分布式事务的更多相关文章

  1. WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程

    今天我们继续学习WCF分布式开发步步为赢系列的12节:WCF事务机制(Transaction)和分布式事务编程.众所周知,应用系统开发过程中,事务是一个重要的概念.它是保证数据与服务可靠性的重要机制. ...

  2. 谈谈分布式事务之三: System.Transactions事务详解[上篇]

    在.NET 1.x中,我们基本是通过ADO.NET实现对不同数据库访问的事务..NET 2.0为了带来了全新的事务编程模式,由于所有事务组件或者类型均定义在System.Transactions程序集 ...

  3. wcf系列学习5天速成——第三天 事务的使用

    今天是速成的第三天,再分享一下WCF中比较常用的一种技术,也就是”事务“. 在B2B的项目中,一般用户注册后,就有一个属于自己的店铺,此时,我们就要插入两张表, User和Shop表. 当然,要么插入 ...

  4. [转载]WCF系列_分布式事务(下)

    浏览到chnking的WCF的分布式事务处理不错,转载过来分享一下. 1. WCF分布式事务例子这里也用转账的例子说事.用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B ...

  5. 三:分布式事务一致性协议2pc和3pc

    一:分布式一致性协议--->对于一个分布式系统进行架构设计的过程中,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是就产生了一系列的一致性协议.--->长期探索涌现出一大批经典的一 ...

  6. WCF分布式事务(EF)

    才说分布式事务,首先,了解一下什么是交易. 事务有四个特性:ACID A是Atomicity,原子性.一个事务往往涉及到很多的子操作,原子性则保证这些子操作要么都做,要么都不做,而不至于出现事务的部分 ...

  7. 分布式事务 & 两阶段提交 & 三阶段提交

    可以参考这篇文章: http://blog.csdn.net/whycold/article/details/47702133 两阶段提交保证了分布式事务的原子性,这些子事务要么都做,要么都不做. 而 ...

  8. 分布式事务(三)mysql对XA协议的支持

    系列目录 分布式事务(一)原理概览 分布式事务(二)JTA规范 分布式事务(三)mysql对XA协议的支持 分布式事务(四)简单样例 分布式事务(五)源码详解 分布式事务(六)总结提高 引子 从Mys ...

  9. 分布式事务专题笔记(三)分布式事务解决方案之TCC(三阶段提交)

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.什么是TCC事务 TCC是Try.Confifirm.Cancel三个词语的缩写,TCC要求每个分支 ...

随机推荐

  1. JAVA环境变量关于

    1.为什么要设置classPath? 用于通知JVM Java基础类库的位置.classPath告诉类装载器去哪里寻找第三方类库 自JDK1.5之后便不需要再配置这个变量了 2.为什么安装两个JRE( ...

  2. SQL Server数据库基础笔记

    启动和停止SQL Server服务三种形式 后台启动服务 计算机->右键->管理->服务和应用程序->服务->sql server(MSSQLSERVER) SQL Se ...

  3. Unity Editor 检查工程Prefab(预设)中的空组件

    在我们做项目的过程中 经常会有预设中出现空的脚本 例如: 导致的原因是因为 脚本的丢失 现在我们来做一个检查工程中有空脚本的预设工具 老规矩直接上代码 放到工程就能用 using UnityEngin ...

  4. Java-将多线程停止的两种方法

    线程如何停止呢 stop方法过时了,看起描述发现,有其他解决方案. 线程结束:就是让线程任务代码执行完,run方法结束. run方法怎么结束呢? run方法中通常都定义循环,只要控制住循环就哦了. / ...

  5. NYOJ116 士兵杀敌(二)

    士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5   描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常 ...

  6. git入门大全

    前言 以前写个一个git小结,但是实际上并不够用.于是结合实际工作上碰到的一些情况,参考了一些资料,重新总结了一下.目标是在日常工作中不用再去查阅其他的资料了,如果有什么遗漏或者错误的地方,请评论指出 ...

  7. 关于JS的时间控制实现动态效果及实例操作

    关于JS的时间控制 <script>        BOM   //Bowers Object Model   浏览器对象模型    setTimeout()//    延迟执行一次   ...

  8. Qt版权符号显示问题

    在个别界面中需要显示版权信息,其中©符号在界面上显示,有时会偏小或者显示为问号~ 其中一种解决办法用html的方式显示实体字符(©>Copyright© 2016</font>&qu ...

  9. IOS中的属性列表----Property List

    属性列表,是一种用来存储串行化后的对象的文件.因为扩展名为plist ,因此通常被称为 plist文件. plist文件通常用于储存用户设置,也可以用于存储捆绑的信息,其内容为xml格式.它可以在程序 ...

  10. JavaJavaScript小问题系列之JSON解析

    1.错误消息及截图 这个很搞笑也很纠结,今天一开发妹子,发现一个问题: 服务端返回字符串"{\"phone\":\"15000000000\"}&qu ...