zoukankan      html  css  js  c++  java
  • WCF(三)分布式事务

    最近在学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 = 9999999,
                        Class = b,
                        Sex = "",
                        Score = 100
                    };
                    ts.Student.Add(a);
                    ts.SaveChanges();     
                }
                return "22222";
            }
           
            [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
            [TransactionFlow(TransactionFlowOption.Allowed)]
            public string AddData_2(string b)
            {
                using (testEntities ts = new testEntities())
                {
                    Student a = new Student()
                    {
                        Age = 9999999,
                        Class = b,
                        Sex = "",
                        Score = 100
                    };
                    ts.Student.Add(a);
                    ts.SaveChanges();
                    throw new Exception("出错拉!");  //抛出错误
                }
    
                return "22222";
            }
        }

    其中标红解释:

    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-350R9O7qiuguochao" />
                    </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("1");
    
                    }
    Console.WriteLine(
    "第一次调用:成功插入一条数据");

              //重新去调用WCF服务
    using (TestService.Service1Client service2 = new TestService.Service1Client()) { //WCF中的AddData_2会报错 service2.AddData_2("2"); } ts.Complete(); } }

    结果:

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

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

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

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

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

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

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

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

  • 相关阅读:
    less的一些用法整理
    flex 布局下关于容器内成员 flex属性的理解
    Web开发者需具备的8个好习惯
    GridView分页功能的实现
    程序员长期保持身心健康的几点建议
    程序员必知的10大基础实用算法
    结对编程
    Python_Day_02 str内部方法总结
    Python_Day_01(使用环境为Python3.0+)
    圆形头像制作
  • 原文地址:https://www.cnblogs.com/qiuguochao/p/7083024.html
Copyright © 2011-2022 走看看