WCF學習筆記之事務編程


一:WCF事務設置

事務提供一種機制將一個活動涉及的所有操作納入到一個不可分割的執行單元;

WCF通過System.ServiceModel.TransactionFlowAttribute特性定義在契約的相應操作方法上;

TransctionFlowOption三個選項:NotAllowed、Allowed、Mandatory不同的事務流轉策略;

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

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

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

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

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

 操作契約上不允許將應用在上面的TransctionFlowAttribute特性指定為:Allowed 或 Mandatory [P143]

 

二:事務與綁定的聯系

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

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

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

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

      屬性OleTransactions(與Default默認一樣)、WSAtomicTransationOctober2004、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 會有我的微信號,如果有問題你也可以在那找到我;當然不感興趣無視此信息;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM