日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

WCF事务编程[中篇]

發(fā)布時(shí)間:2024/10/8 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WCF事务编程[中篇] 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

[續(xù)《上篇》]通過(guò)將TransactionFlowAttribute特性應(yīng)用在服務(wù)契約的某個(gè)操作之上,并指定相應(yīng)的TransactionFlowOption枚舉直,僅僅定義了事務(wù)流轉(zhuǎn)的策略而已。或者說(shuō),通過(guò)這種方式確定對(duì)事物流轉(zhuǎn)的一種意愿,客戶端是否愿意將當(dāng)前事務(wù)流出,服務(wù)端是否愿意接受流入的事務(wù),可以通過(guò)TransactionFlowAttribute特性進(jìn)行控制。所以說(shuō),服務(wù)操作上定義個(gè)TransactionFlowAttribute特性是是否進(jìn)行事務(wù)流轉(zhuǎn)的總開(kāi)關(guān),真正的事務(wù)傳播是建立在TransactionFlowOption.Allowed或者TransactionFlowOption.Mandatory之上的。

至于WCF框架是否有能力對(duì)事物進(jìn)行流轉(zhuǎn),按照怎樣的協(xié)議進(jìn)行流轉(zhuǎn),則是通過(guò)綁定實(shí)現(xiàn)的,現(xiàn)在我們首先看看怎樣的綁定具有事務(wù)流轉(zhuǎn)的能力。

一、綁定對(duì)事務(wù)流轉(zhuǎn)的支持

WCF技術(shù)剖析(卷1)》中的第3章對(duì)綁定的本質(zhì)進(jìn)行了深層次的剖析,閱讀過(guò)本章的讀者應(yīng)該知道:綁定是一系列綁定元素(BindingElement)的有序組合,相應(yīng)的綁定元素對(duì)消息進(jìn)行相應(yīng)的處理以實(shí)現(xiàn)特定的目標(biāo),比如MessageEncodingBindingElement實(shí)現(xiàn)對(duì)消息的編碼和解碼,TransportBindingElement實(shí)現(xiàn)對(duì)消息的傳輸。

消息交換是WCF進(jìn)行通信的唯一手段,任何需要傳輸?shù)臄?shù)據(jù)最終都需要最為消息的一部分。對(duì)象事務(wù)流轉(zhuǎn)來(lái)說(shuō),客戶端需要將當(dāng)前事務(wù)進(jìn)行序列化并嵌入到消息中;服務(wù)端則需要從接收到的消息中提取事務(wù)相關(guān)信息,反序列化以重建事務(wù)。這樣的操作同樣實(shí)現(xiàn)在一個(gè)綁定元素中,即TransactionFlowBindingElement

既然TransactionFlowBindingElement實(shí)現(xiàn)了對(duì)事物的流轉(zhuǎn),那么我們就可以根據(jù)某個(gè)綁定對(duì)象的綁定元素集合中是否包含該元素判斷綁定是否支持事務(wù)流轉(zhuǎn)。為此,我寫了如下一個(gè)簡(jiǎn)單的方法,傳入相應(yīng)的Binding對(duì)象,打印出相應(yīng)的綁定類型是否支持事務(wù)流轉(zhuǎn):

1: static void PrintTransactionFlowSupport(Binding binding) 2: { 3: TransactionFlowBindingElement transactionFlowElement = binding.CreateBindingElements().Find< TransactionFlowBindingElement>(); 4: Console.WriteLine("{0,-30} {1}",binding.GetType().Name,transactionFlowElement!=null?"Yes":"No"); 5: }

現(xiàn)在,我們通過(guò)調(diào)用PrintTransactionFlowSupport方法,判斷所有的系統(tǒng)綁定是否為事務(wù)流轉(zhuǎn)提供支持。從輸出結(jié)果來(lái)看,除了BasicHttpBindingNetMsmqBindingMsmqIntegrationBinding三種,其余的系統(tǒng)綁定均包含TransactionFlowBindingElement綁定元素,也就是說(shuō)它們均具有對(duì)事務(wù)就是傳播的能力。

1: class Program 2: { 3: static void Main(string[] args) 4: { 5: Console.WriteLine("{0,-30} {1}", "Binding", "Transaction Flow"); 6: Console.WriteLine("--------------------------------------------"); 7: //BasicHttpBinding 8: PrintTransactionFlowSupport(new BasicHttpBinding()); 9: 10: //WS Binding 11: PrintTransactionFlowSupport(new WSHttpBinding()); 12: PrintTransactionFlowSupport(new WS2007HttpBinding()); 13: PrintTransactionFlowSupport(new WSDualHttpBinding()); 14: PrintTransactionFlowSupport(new WSFederationHttpBinding()); 15: PrintTransactionFlowSupport(new WS2007FederationHttpBinding()); 16: 17: //TCP and IPC Binding 18: PrintTransactionFlowSupport(new NetTcpBinding()); 19: PrintTransactionFlowSupport(new NetNamedPipeBinding()); 20: //MSMQ Binding 21: PrintTransactionFlowSupport(new NetMsmqBinding()); 22: PrintTransactionFlowSupport(new MsmqIntegrationBinding()); 23: } 24: }

輸出結(jié)果:

Binding Transaction Flow ----------------------------------------------- BasicHttpBinding No WSHttpBinding Yes WS2007HttpBinding Yes WSDualHttpBinding Yes WSFederationHttpBinding Yes WS2007FederationHttpBinding Yes NetTcpBinding Yes NetNamedPipeBinding Yes NetMsmqBinding No MsmqIntegrationBinding No

由于BasicHttpBinding基于WS-I Basic Profile標(biāo)準(zhǔn)的綁定,而兩個(gè)基于MSQM的綁定(NetMsmqBindingMsmqIntegrationBinding)只能采用單向(One-Way)的消息交換模式,所以它們不具有事務(wù)流轉(zhuǎn)的能力。但是,即使對(duì)于契約的支持事務(wù)的綁定類型,事務(wù)流轉(zhuǎn)默認(rèn)也是被關(guān)閉的,在真正需要事先事務(wù)流轉(zhuǎn)的場(chǎng)景中,需要通過(guò)配置或者編成的方式開(kāi)啟該選項(xiàng)。此外,事務(wù)流轉(zhuǎn)涉及事務(wù)在消息中的格式化問(wèn)題,而事務(wù)的格式化決定于采用的協(xié)議。通過(guò)《談?wù)劮植际绞聞?wù)之四: 兩種事務(wù)處理協(xié)議OleTx與WS-AT》我們知道,WCF支持三種不同的事務(wù)處理協(xié)議:OleTx,WS-AT 1.0和WS-AT 1.0。事務(wù)處理協(xié)議通過(guò)類型TransactionProtocol類型表示,TransactionProtocol定義如下:

1: public abstract class TransactionProtocol 2: { 3: public static TransactionProtocol Default { get; } 4: 5: public static TransactionProtocol OleTransactions { get; } 6: public static TransactionProtocol WSAtomicTransactionOctober2004 { get; } 7: public static TransactionProtocol WSAtomicTransaction11 { get; } 8: }

TransactionProtocol是一個(gè)抽象類,定義了三種靜態(tài)只讀屬性O(shè)leTransactions、WSAtomicTransactionOctober2004和WSAtomicTransaction11,用于獲取分別代表OleTx,WS-AT 1.0和WS-AT 1.0三種協(xié)議的具體TransactionProtocol對(duì)象。這三種具體的TransactionProtocol類型以內(nèi)部(Internal)類型的方式定義。Default制度屬性返回默認(rèn)的事務(wù)處理協(xié)議,和OleTransactions屬性值一致。

對(duì)于NetTcpBindingNetNamedPipeBinding來(lái)說(shuō),我們可以通過(guò)屬性TransactionFlow設(shè)置或者獲取綁定是否支持事務(wù)流轉(zhuǎn)的開(kāi)關(guān),并通過(guò)TransactionProtocol屬性設(shè)置或者獲取綁定支持的事務(wù)處理協(xié)議。

1: public class NetTcpBinding : Binding, IBindingRuntimePreferences 2: { 3: //其他成員 4: public bool TransactionFlow { get; set; } 5: public TransactionProtocol TransactionProtocol { get; set; } 6: } 7: 8: public class NetNamedPipeBinding : Binding, IBindingRuntimePreferences 9: { 10: //其他成員 11: public bool TransactionFlow { get; set; } 12: public TransactionProtocol TransactionProtocol { get; set; } 13: }

而對(duì)于基于WS的綁定來(lái)說(shuō),由于綁定本身就是為跨平臺(tái)和互操作涉及的,所以僅僅支持基于WS-AT的事務(wù)處理協(xié)議,其中WSHttpBindingWSDualHttpBindingWSFederationHttpBinding支持的協(xié)議是WS-AT 1.0,而WS2007HttpBindingWS2007FederationHttpBinding支持的是WS-AT 1.1。所以,它們僅僅具有TransactionFlow屬性,并沒(méi)有TransactionProtocol屬性,該屬性定義在它們的基類WSHttpBindingBase上面:

1: public abstract class WSHttpBindingBase : Binding, IBindingRuntimePreferences 2: { 3: //其他成員 4: public bool TransactionFlow { get; set; } 5: }

系統(tǒng)綁定的TransactionFlow和TransactionProtocol屬性(僅限于NetTcpBindingNetNamedPipeBinding)可以通過(guò)配置的方式指定。下面的配置中定義了開(kāi)啟了transactionFlow開(kāi)關(guān)的兩個(gè)綁定(NetTcpBinding和WS2007HttpBinding),并將其中的NetTcpBinding的TransactionProtocol設(shè)置成基于WS-AT 1.0的協(xié)議(transactionProtocol="WSAtomicTransactionOctober2004")。

1: <?xml version="1.0" encoding="utf-8" ?> 2: <configuration> 3: <system.serviceModel> 4: <bindings> 5: <netTcpBinding> 6: <binding name="transactionalTcpBinding" transactionFlow="true" transactionProtocol="WSAtomicTransactionOctober2004" /> 7: </netTcpBinding> 8: <ws2007HttpBinding> 9: <binding name="transactionalHttpBinding" transactionFlow="true" /> 10: </ws2007HttpBinding> 11: </bindings> 12: <services> 13: <service name="Artech.TransactionalServices.BankingService"> 14: <endpoint address="net.tcp://127.0.0.1/bankingservice" binding="netTcpBinding" 15: bindingConfiguration="transactionalTcpBinding" contract="Artech.TransactionalServices.IBankingService" /> 16: <endpoint address="http://127.0.0.1/bankingservice" binding="ws2007HttpBinding" 17: bindingConfiguration="transactionalHttpBinding" contract="Artech.TransactionalServices.IBankingService" /> 18: </service> 19: </services> 20: </system.serviceModel> 21: </configuration>

如果現(xiàn)有的系統(tǒng)綁定不能滿足你的需要(比如你需要同時(shí)采用HTTP傳輸協(xié)議和OleTx事務(wù)處理協(xié)議),可以通過(guò)編程或者配置的方式創(chuàng)建自定的綁定(CustomBinding)。創(chuàng)建支持事務(wù)流轉(zhuǎn)的自定義綁定的時(shí)候,你需要做的僅僅是將TransactionFlowBindingElement添加到綁定元素集合中,并設(shè)置TransactionFlow和TransactionProtocol屬性即可。下面的配置就定義了這樣一個(gè)基于OleTx的HTTP綁定。

1: <?xml version="1.0" encoding="utf-8" ?> 2: <configuration> 3: <system.serviceModel> 4: <bindings> 5: <customBinding> 6: <binding name="transactionalBinding"> 7: <textMessageEncoding /> 8: <transactionFlow transactionProtocol="OleTransactions"/> 9: <httpTransport /> 10: </binding> 11: </customBinding> 12: </bindings> 13: <services> 14: <service name="Artech.TransactionalServices.BankingService"> 15: <endpoint address="http://127.0.0.1/bankingservice" binding="customBinding" 16: bindingConfiguration="transactionalBinding" contract="Artech.TransactionalServices.IBankingService" /> 17: </service> 18: </services> 19: </system.serviceModel> 20: </configuration>

二、 綁定與TransactionFlow設(shè)置

通過(guò)應(yīng)用TransactionFlowAttribute特性為某個(gè)操作設(shè)置相應(yīng)的事務(wù)流轉(zhuǎn)策略,綁定決定了實(shí)現(xiàn)事務(wù)流轉(zhuǎn)的能力和方式,兩個(gè)的不同組合表現(xiàn)出不同的事務(wù)流轉(zhuǎn)行為。在這里,事務(wù)的流轉(zhuǎn)包含兩個(gè)層面的意思,即事務(wù)的流出或者發(fā)送,以及事務(wù)的流入或者接收。對(duì)于WCF的客戶端框架來(lái)說(shuō),對(duì)于通過(guò)TransactionFlowAttribute特性設(shè)置的三個(gè)選項(xiàng)來(lái)說(shuō),NotAllowed和Allowed對(duì)綁定的事務(wù)流轉(zhuǎn)能力沒(méi)有任何要求,而Madantory則強(qiáng)制要求終結(jié)點(diǎn)的綁定能夠?qū)崿F(xiàn)事務(wù)的流轉(zhuǎn)(綁定本身能夠支持事務(wù)流轉(zhuǎn)并且TransactionFlow開(kāi)關(guān)必須開(kāi)啟)。結(jié)合上面所介紹的,事務(wù)流轉(zhuǎn)選項(xiàng)和綁定類型兩兩組合所表現(xiàn)出的行為如下面的表格所示(這里的事務(wù)綁定表示TransactionFlow開(kāi)關(guān)開(kāi)啟的支持事務(wù)流轉(zhuǎn)的綁定)。

事務(wù)綁定

非事務(wù)綁定

NotAllowed

當(dāng)前事務(wù)不需要存在,存在的當(dāng)前事務(wù)不會(huì)被流出

當(dāng)前事務(wù)不需要存在,存在的當(dāng)前事務(wù)不會(huì)被流出

Allowed

當(dāng)前事務(wù)不需要存在,存在的當(dāng)前事務(wù)會(huì)被流出

當(dāng)前事務(wù)不需要存在,存在的當(dāng)前事務(wù)不會(huì)被流出

Mandatory

當(dāng)前事務(wù)必須存在,存在的當(dāng)前事務(wù)會(huì)被流出

不合法的組合

對(duì)于一個(gè)服務(wù)契約來(lái)說(shuō),如果任何一個(gè)操作的TransactionFlow選項(xiàng)被定義成Mandatory,相應(yīng)終結(jié)點(diǎn)所采用的綁定必須是事務(wù)綁定(接下來(lái)我們將本身支持事務(wù)流轉(zhuǎn),并開(kāi)啟了TransactionFlow開(kāi)關(guān)的綁定稱為事務(wù)綁定)。下面的代碼和配置中,通過(guò)TransactionFlowAttribute將唯一的Transfer操作的事務(wù)流轉(zhuǎn)選項(xiàng)設(shè)置為Mandatory,并選用不支持事務(wù)流轉(zhuǎn)的BasicHttpBinding。當(dāng)使用創(chuàng)建的ChannelFactory<TChannel>創(chuàng)建服務(wù)代理的時(shí)候,拋出如圖1所示的InvalidOperationException異常。

1: [ServiceContract(Namespace="http://www.artech.com/")] 2: public interface IBankingService 3: { 4: [OperationContract] 5: [TransactionFlow(TransactionFlowOption.Mandatory)] 6: void Transfer(string accountFrom, string accountTo, double amount); 7: } 1: <?xml version="1.0" encoding="utf-8" ?> 2: <configuration> 3: <system.serviceModel> 4: <client> 5: <endpoint address="http://127.0.0.1:3721/bankingservice" binding="basicHttpBinding" contract="Artech.TransactionalServices.IBankingService" name="bankingservice" /> 6: </client> 7: </system.serviceModel> 8: </configuration>

圖1 客戶端在Mandatory事務(wù)流轉(zhuǎn)選項(xiàng)情況下采用非事務(wù)綁定拋出的異常

上面所說(shuō)的是不同的事務(wù)流轉(zhuǎn)選項(xiàng)和綁定類型在客戶端的表現(xiàn)行為,現(xiàn)在我們將目光轉(zhuǎn)移到服務(wù)端。較之客戶端,服務(wù)的情況要稍微復(fù)雜一些,處理考慮事務(wù)流轉(zhuǎn)選項(xiàng)和綁定對(duì)事務(wù)流轉(zhuǎn)的支持之外,還需要考慮以下三個(gè)因素:

  • 接收的消息中是否具有包含流入事務(wù)的SOAP報(bào)頭;
  • 如果包括需要考慮流入事務(wù)在SOAP報(bào)頭中的XML格式是否與綁定采用的事務(wù)處理協(xié)議一致;
  • 如果不一致需要考慮事務(wù)報(bào)頭的MustUnderstand屬性是True(或1)還是False(或者0)。

WCF服務(wù)端服務(wù)流轉(zhuǎn)表現(xiàn)出來(lái)的最終行為決定于上述的五個(gè)要素,下面的表格流出了它們之間不同的組合最終表現(xiàn)出來(lái)的事務(wù)處理行為。

首先,如果一個(gè)服務(wù)契約的任何一個(gè)操作的TransactionFlow選項(xiàng)定義成Mandatory,那么強(qiáng)制要求相應(yīng)的終結(jié)點(diǎn)采用事務(wù)綁定。比如說(shuō),同樣對(duì)于上面定義的IBankingService服務(wù)契約(TransactionFlow),但是使用默認(rèn)的WS2007HttpBinding(默認(rèn)情況下TransactionFlow是關(guān)閉的),在進(jìn)行服務(wù)寄宿的時(shí)候,會(huì)拋出如圖2所示的InvalidOperationException異常。

1: <?xml version="1.0" encoding="utf-8" ?> 2: <configuration> 3: <system.serviceModel> 4: <services> 5: <service name="Artech.TransactionalServices.BankingService"> 6: <endpoint address="http://127.0.0.1:3721/bankingservice" binding="ws2007HttpBinding" contract="Artech.TransactionalServices.IBankingService" /> 7: </service> 8: </services> 9: </system.serviceModel> 10: </configuration>

圖2 客戶端在Mandatory事務(wù)流轉(zhuǎn)選項(xiàng)情況下采用非事務(wù)綁定拋出的異常

其次,同樣對(duì)于TransactionFlow選項(xiàng)為Mandatory的操作,如果接收的消息并不包含流入事務(wù)的SOAP報(bào)頭,或者說(shuō)流入的事務(wù)在SOAP報(bào)頭中的表示并不符合綁定采用的事務(wù)處理協(xié)議,由于Mandatory選項(xiàng)在服務(wù)端的含義就是強(qiáng)制需要流入一個(gè)可以理解的事務(wù),在這種情況下服務(wù)端會(huì)返回一個(gè)Fault消息,并導(dǎo)致客戶端拋出異常。同樣是對(duì)于前面給定義的IBankingService服務(wù)契約,如果我們將客戶端和服務(wù)端終結(jié)點(diǎn)的綁定配置成不同的事務(wù)處理協(xié)議,比如客戶端采用默認(rèn)的OleTx,服務(wù)端則采用WS-AT 1.1。客戶端在進(jìn)行服務(wù)調(diào)用的時(shí)候,會(huì)拋出如圖3所示的ProtocolException異常。

客戶端配置:

1: <?xml version="1.0" encoding="utf-8" ?> 2: <configuration> 3: <system.serviceModel> 4: <bindings> 5: <netTcpBinding> 6: <binding name="nonTransactionalBinding" transactionFlow="true"/> 7: </netTcpBinding> 8: </bindings> 9: <client> 10: <endpoint address="net.tcp://127.0.0.1:3721/bankingservice" binding="netTcpBinding" bindingConfiguration="nonTransactionalBinding" contract="Artech.TransactionalServices.IBankingService" name="bankingservice" /> 11: </client> 12: </system.serviceModel> 13: </configuration>

服務(wù)端配置:

1: <?xml version="1.0" encoding="utf-8" ?> 2: <configuration> 3: <system.serviceModel> 4: <bindings> 5: <netTcpBinding> 6: <binding name="transactionalBinding" transactionFlow="true" transactionProtocol="WSAtomicTransaction11" /> 7: </netTcpBinding> 8: </bindings> 9: <services> 10: <service name="Artech.TransactionalServices.BankingService"> 11: <endpoint address="net.tcp://127.0.0.1:3721/bankingservice" binding="netTcpBinding" 12: bindingConfiguration="transactionalBinding" contract="Artech.TransactionalServices.IBankingService" /> 13: </service> 14: </services> 15: </system.serviceModel> 16: </configuration>

圖3 客戶端端和服務(wù)端采用不同的事務(wù)處理協(xié)議導(dǎo)致的異常(Mandatory)

倘若接收到的消息中存在事務(wù)報(bào)頭,并且報(bào)頭的MustUnderstand屬性為True或者1,對(duì)于Allowed選項(xiàng)來(lái)說(shuō),如果采用非事務(wù)綁定,或者說(shuō)雖然采用事務(wù)綁定,但是事務(wù)報(bào)頭與綁定采用的事務(wù)處理協(xié)議不符。在這種情況下,服務(wù)端不能有效地理解事務(wù)報(bào)頭,也會(huì)向客戶端返回一個(gè)Fault消息,并導(dǎo)致客戶端拋出異常。比如說(shuō),我們采用上面提供的配置(客戶端和服務(wù)端綁定采用不同的事務(wù)處理協(xié)議),如果我們將服務(wù)契約IBankingService的Transfer操作的TransactionFlow選項(xiàng)設(shè)置為Allowed,客戶端在進(jìn)行服務(wù)調(diào)用的時(shí)候會(huì)拋出如圖4所示的ProtocolException異常。但是,如果MustUnderstand屬性為False或者0,事務(wù)報(bào)頭會(huì)被忽略。

1: [ServiceContract(Namespace = "http://www.artech.com/")] 2: public interface IBankingService 3: { 4: [OperationContract] 5: [TransactionFlow(TransactionFlowOption.Allowed)] 6: void Transfer(string accountFrom, string accountTo, double amount); 7: }

圖4 客戶端端和服務(wù)端采用不同的事務(wù)處理協(xié)議導(dǎo)致的異常(Allowed)

相似情況同樣發(fā)生在TransactionFlow選項(xiàng)為NotAllowed的時(shí)候,所不同的是:即使接收到的事務(wù)報(bào)頭與綁定采用的事務(wù)處理協(xié)議相匹配,仍然會(huì)導(dǎo)致事務(wù)報(bào)頭不能理解的異常。

轉(zhuǎn)載于:https://www.cnblogs.com/liwei823/archive/2011/09/14/2176654.html

總結(jié)

以上是生活随笔為你收集整理的WCF事务编程[中篇]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。