WCF學習筆記之事務編程

一:WCF事務設置git

事務提供一種機制將一個活動涉及的全部操做歸入到一個不可分割的執行單元;github

WCF經過System.ServiceModel.TransactionFlowAttribute特性定義在契約的相應操做方法上;編程

TransctionFlowOption三個選項:NotAllowed、Allowed、Mandatory不一樣的事務流轉策略;微信

1:NotAllowed(默認) 客戶端的事務不會容許被流轉到服務端,服務端也不會試圖去接收流入的事務;分佈式

2:Allowed 若是客戶端的事務在,則被流轉到服務端,服務端會試圖去接收流入的事務;ide

3:Mandatory 客戶端必須在一個事務中進行服務調用,相應的事務會被流轉到服務端。服務端接收到的消息  中必須包含被序列化的事務;學習

    [ServiceContract]
    public interface IBankingService
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        void Transfer(string fromAccountId, string toAccountId, double amount);
    }

因爲分佈式事務在客戶端和服務端之間協調過程依賴於它們之間的相互消息交換,所以在一個單向(One-Way)ui

 操做契約上不容許將應用在上面的TransctionFlowAttribute特性指定爲:Allowed 或 Mandatory [P143]spa

 

二:事務與綁定的聯繫.net

支持事務綁定的除BasicHttpBinding(基於WS-I Basic Profile標準綁定)、NetMsmqBinding(只能採用單工的消息交換)、

      MsmqIntegrationBinding(只能採用單工的消息交換) 其它都有事務的流轉能力;

支持事務的綁定流轉默認也是被關閉,要經過配置或者編程的方式開啓該選項;

WCF支持三種不一樣的事務處理協議:OleTx、WS-AT 1.0、WS-AT 1.1 分別對應於TransactionProtocol中的三個靜態只讀

      屬性OleTransactions(與Default默認同樣)、WSAtomicTransationOctober200四、WSAtomicTransaction11

NetTcpBinding和NetNamedPipeBinding經過TransactionFlow設置支持事務的開關,TransactionProtocol設置事務協議;

WSHttpBinding、WSDualHttpBinding和WSFedrationHttpBinding支持協議WS-AT 1.0,而WS2007HttpBinding和

WS2007FederationHttpBinding支持協議WS-AT 1.1,它們僅僅只有TransactionFlow 沒有TransactionProtocol設置事務協議;

<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="transactionalTcpBinding" transactionFlow="true"
                 transactionProtocol="WSAtomicTransactionOctober2004">
        </binding>
      </netTcpBinding>

      <ws2007HttpBinding>
        <binding name="transactionalHttpBinding" transactionFlow="true"></binding>
      </ws2007HttpBinding>
    </bindings>
    <services>
      <service name="Service.WithdrawService">
        <endpoint binding="customBinding"
                  bindingConfiguration="transactionalTcpBinding"
                  contract="Service.Interface.IWithdrawService" />
      </service>
      <service name="Service.DepositService">
        <endpoint binding="customBinding"
                  bindingConfiguration="transactionalHttpBinding" 
                  contract="Service.Interface.IDepositService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

 

三:經過服務(操做)行爲控制事務

經過服務契約肯定事務流轉的策略,經過事務綁定實施事務的流轉;經過服務操做設置提交方式及是否自動登記到事務之中

服務操做OperationBehaviorAttribute兩個事務管理相關的屬性:TransactionAutoComplete 和 TransactionScopeRequired

1:TransactionAutoComplete(默認值Flase) 表示相應操做的執行是否自動歸入一個事務中;

2:TransactionScopeRequired(默認值true) 表示若是執行過程沒有拋出異常,完成後將自動提交事務;

    public class BankingService : IBankingService
    {       
        [OperationBehavior(TransactionScopeRequired = true)]
        public void Transfer(string fromAccountId, string toAccountId, double amount)
        {
        }
    }

 

四:事務相關的服務行爲

ServiceBehaviorAttribute定義的4個與事務相關的屬性;

1:TransactionIsolationLevel:事務的隔離級別,默認值爲IsolationLevel.Seriallizable;

2:TransactionTimeout 以字符串形式定義事務的超時時限;

3:TransactionAutoCompleteOnSessionClose 在會話正常結束(沒有異常)以後是否自動提交或完成開啓的事務,默認值False

4:ReleaseServiceInstanceOnTransactionComplete 當事務完成以後是否要將服務實例釋放掉,默認值False

    [ServiceBehavior(TransactionIsolationLevel=IsolationLevel.ReadCommitted,TransactionTimeout="00:05:00",
                     TransactionAutoCompleteOnSessionClose=true)]
    public class WithdrawService : IWithdrawService
    {
        [OperationBehavior(TransactionScopeRequired = true)]
        public void Withdraw(string accountId, double amount)
        {
        }
    }

注意:若契給服務ServiceBehavior定義的那些屬性後 若在其內的操做沒有一個設置OperationBehavior(TransactionScopeRequired = true)則會報錯;

也可使用配置方式:

      <service name="Service.DepositService" behaviorConfiguration="transactionBehavior">
        <endpoint binding="customBinding"
                  contract="Service.Interface.IDepositService" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="transactionBehavior">
          <serviceTimeouts transactionTimeout="00:30:00"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>


在事務流轉的場景中,流入的事務和目標服務的事務隔離級別必須一致;不然會報異常;客戶端調用代碼以下;

沒有定義事務的級別則採用默認隔離級別Serializable;

using System.ServiceModel;
using Service.Interface;
using System.Transactions;

namespace TransactionalService.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ChannelFactory<IBankingServicee> channelFactory = new ChannelFactory<IBankingServicee>("bankingservice"))
            {
                IBankingServicee bankingservice = channelFactory.CreateChannel();
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    bankingservice.Transfer();
                    transactionScope.Complete();
                }
            }
        }
    }
}

 

五:事務實例:

接下來將經過一個簡單的事實來介紹一下WCF事務;由於比較簡單因此後面直接提供源代碼的下載[源代碼裏面還包括其它信息]:

1:首先是契約的定義:

using System.ServiceModel;
using System.Runtime.Serialization;
using Service.Model;
namespace Service.Interface
{
    [ServiceContract(SessionMode=SessionMode.Required)]
    public interface ITransactionDemo
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        void AddAccount(AccountModel model);

        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        void OutAccount(AccountModel model);
    }
}

2:契約服務的實現內容

using Service.Interface;
using Service.Model;
using System.Data.Common;
using System.ServiceModel;
using Service.DAL;
using System.EnterpriseServices;
using System.Transactions;
namespace Service.ServerDeom
{
    [ServiceBehavior(TransactionIsolationLevel = IsolationLevel.Serializable,
    TransactionTimeout = "00:05:00",
    TransactionAutoCompleteOnSessionClose = true)]
    public class TransactionDemoService:ITransactionDemo
    {
        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
        public void AddAccount(AccountModel model)
        {
            try
            {
                AccountDAL.Update(model);
            }
            catch (Exception ex)
            {
                throw new FaultException(new FaultReason(ex.Message));
            }
        }

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
        public void OutAccount(AccountModel model)
        {
            try
            {
                AccountDAL.Update(model);
            }
            catch (Exception ex)
            {
                throw new FaultException(new FaultReason(ex.Message));
            }
        }
    }
}

3:宿主服務的配置

<bindings>
      <netTcpBinding>
        <binding name="portSharingBinding" portSharingEnabled="true"></binding>
      </netTcpBinding>
      <ws2007HttpBinding>
        <binding name="transactionalTcpBinding" transactionFlow="true" />
      </ws2007HttpBinding>
    </bindings>
<services>
<service name="Service.ServerDeom.TransactionDemoService">
        <endpoint address="http://127.0.0.1:3724/ExcptDivideService"
                  binding="ws2007HttpBinding"
                   bindingConfiguration="transactionalTcpBinding"
                  contract="Service.Interface.ITransactionDemo"/>
      </service>
    </services>

4:客戶端的配置信息

      <endpoint name="TransactionAccount" address="http://127.0.0.1:3724/ExcptDivideService"
          binding="ws2007HttpBinding"
          contract="Service.Interface.ITransactionDemo"/>

5:客戶端的實現代碼:

 AccountModel model = new AccountModel();
            model.Money = 25;
            model.Uid = 1;
            model.ID = 1;

            AccountModel OutModel = new AccountModel();
            OutModel.ID =10;
            OutModel.Uid = 2;
            OutModel.Money = 1;

            using (ChannelFactory<ITransactionDemo> ChannelFactory = new ChannelFactory<ITransactionDemo>("TransactionAccount"))
            {
                ITransactionDemo proxy = ChannelFactory.CreateChannel();
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    try
                    {
                        proxy.AddAccount(model);
                        throw new Exception();
                        proxy.OutAccount(OutModel);
                        transactionScope.Complete();
                    }
                    catch (Exception ex)
                    {
                        (proxy as ICommunicationObject).Abort();
                    }

                }

 

 

本文是學習[WCF全面解析]中有關事務編程的內容;針對WCF事務編程作一個簡單的要點記錄;

若是,您認爲閱讀這篇博客讓您有些收穫,不妨點擊一下右下角的推薦按鈕。  由於,個人寫做熱情也離不開您的確定支持。

感謝您的閱讀,[源代碼下載]

 

最近有個妹子弄的一個關於擴大眼界跟內含的訂閱號,天天都會更新一些深度內容,在這裏若是你感興趣也能夠關注一下(嘿對美女跟知識感興趣),固然能夠關注後輸入:github 會有個人微信號,若是有問題你也能夠在那找到我;固然不感興趣無視此信息;

相關文章
相關標籤/搜索