|
系列文章導(dǎo)航:
WCF從理論到實(shí)踐(2):決戰(zhàn)紫禁之巔
WCF從理論到實(shí)踐(3):八號當(dāng)鋪之黑色契約
WCF從理論到實(shí)踐(5):Binding細(xì)解
WCF從理論到實(shí)踐(9):實(shí)例模式和對象生命周期
WCF從理論到實(shí)踐(16):操作重載(帶視頻+ppt+源碼)
WCF從理論到實(shí)踐(17):OO大背離(帶視頻+ppt+源碼)
本文目的
通過閱讀本文,您能了解以下知識
1) 如何在WCF中實(shí)現(xiàn)事務(wù)?
2) 談?wù)勈聞?wù)隔離方式的相關(guān)知識
3) 事務(wù)的實(shí)現(xiàn)會給我們編程帶來什么樣的阻力?
4) 一筆帶過,WCF是如何實(shí)現(xiàn)分布式事務(wù)的?
5) 代碼不騙人,用一個銀行存取款的范例來演練WCF事務(wù)
本文適合的讀者
本文適合WCF初學(xué)者,學(xué)習(xí)本文之前,您最好閱讀一下WCF從理論到實(shí)踐系列文章的前幾篇
如何在WCF中實(shí)現(xiàn)事務(wù)?
事務(wù)原本是一件難于實(shí)現(xiàn)的事情,可WCF總是能化腐朽為神奇,它能夠通過簡單的聲明式編程方式,便可以實(shí)現(xiàn)分布式的事務(wù),下面就來看下實(shí)現(xiàn)此目標(biāo)的功臣:
1) TransactionFlowAttribute:操作契約(OperationContractAttribute)的一個屬性,它能夠指示所屬操作(Operation)的事務(wù)選項(TransactionFlowOption)。
2) TransactionFlowOption:它是TransactionFlowAttribute構(gòu)造函數(shù)中的參數(shù),是一個枚舉(enum),包括三個枚舉項NotAllowed:不允許事務(wù),是缺省值;Allowed:允許事務(wù),意味著事務(wù)可有可無;Mandatory:強(qiáng)制事務(wù),表示事務(wù)是必須的。
3) TransactionAutoCompleteOnSessionClose:它是操作行為(OperationBehaviorAttribute)的一個屬性,用于標(biāo)注事務(wù)完成之后,服務(wù)端實(shí)例是否自動釋放,這個屬性和服務(wù)對象實(shí)例模式緊密相關(guān),使用的時候,應(yīng)該著重小心,下面也會有說明。
4) TransactionIsolationLevel:也是操作行為(OperationBehaviorAttribute)的一個屬性,用于指示事務(wù)隔離方式(isolation level).包括5中選項:Any,ReadUncommitted,ReadCommitted,RepeatableRead,Serializable,事務(wù)的隔離方式相關(guān)知識比較復(fù)雜,留作文章的第二點(diǎn)中將具體闡述
5) TransactionTimeout:也是操作行為(OperationBehaviorAttribute)的一個屬性,用于指示事務(wù)的超時時間,默認(rèn)為TimeSpan.Zero,表示不會受超時時間的限制..:: OperationBehaviorAttribute:也是操作行為(OperationBehaviorAttribute)的一個屬性,用于指示分布式事務(wù)選項,如果設(shè)置為true,那么必須在事務(wù)范圍(Transaction Scorp)內(nèi)。
通過上面幾個屬性的使用,我們便能夠輕松的在WCF中實(shí)現(xiàn)事務(wù)以及分布式事務(wù)。具體實(shí)現(xiàn)方式可以參考代碼范例
談?wù)勈聞?wù)隔離方式的相關(guān)知識
單純的事務(wù)存在著下面三個問題
1) 臟讀:簡單的說就是事務(wù)一在某一時刻更改了數(shù)據(jù),恰恰這個更改的數(shù)據(jù)被事務(wù)二讀取,而事務(wù)一卻最終失敗,導(dǎo)致數(shù)據(jù)回滾,那事務(wù)二就是一個受騙者
2) 非可重復(fù)性讀取:同一數(shù)據(jù)每次讀取的結(jié)果都不一樣就是非可重復(fù)讀取。比如事務(wù)一要讀取的數(shù)據(jù)務(wù)二改變,這就是非可重復(fù)性讀取
3) 幻讀:很簡單,比如事務(wù)一在查詢數(shù)據(jù)中,事務(wù)二卻插入了一個符合查詢條件的數(shù)據(jù),這樣就造成新插入數(shù)據(jù)的幻讀。
三種問題的解釋可能比較難于理解,其實(shí)簡單的說,臟讀是讀了別人正在更改的數(shù)據(jù),而可重復(fù)讀取是更改了別人正在讀的數(shù)據(jù),而幻讀呢則是讀了別人還未來得及插入,更改或者刪除的數(shù)據(jù),我想這樣理解就簡單多了。
針對上面不同的問題,可以設(shè)置事務(wù)的不同隔離方式來防止問題的發(fā)生,事務(wù)的隔離方式又包括
1) Any: 組件的隔離級別是從調(diào)用組件的隔離級別獲得的。如果組件是根組件,則隔離級別用于 Serializable 中。
2) ReadUncommitted:讀取未提交數(shù)據(jù),該方式在讀取數(shù)據(jù)時保持共享鎖定以避免讀取已修改的數(shù)據(jù),但在事務(wù)結(jié)束前可以更改這些數(shù)據(jù),這導(dǎo)致非可重復(fù)讀取或幻讀。
3) ReadCommitted:讀取提交數(shù)據(jù), 發(fā)出共享鎖定并允許非獨(dú)占方式的鎖定。該方式與讀取未提交數(shù)據(jù)相相似,這種方式看似和讀取未提交數(shù)據(jù)相似,但有一個區(qū)別,事務(wù)的只讀鎖在移到下一行的時候,會解鎖,而寫入鎖卻只有在事務(wù)完成或者被中止后才解鎖,事務(wù)要等待所有寫入鎖解鎖。
4) RepeatableRead:可重復(fù)性讀取,與讀取提交數(shù)據(jù)相似,在查詢中使用的所有數(shù)據(jù)上放置鎖,以防止其他用戶更新這些數(shù)據(jù)。防止非可重復(fù)讀取,但幻讀行仍有可能發(fā)生。該方式是只讀鎖也要等到事務(wù)結(jié)束或者中止才解除
5) Serializable:在完成事務(wù)前防止更新或插入。
從上面的描述看,幾種隔離方式比較難于區(qū)分,但它們能解決事務(wù)面臨的不同問題,也許記住這些更方便的了解隔離方式
隔離級別 | ReadUncommitted | ReadCommitted | RepeatableRead | Serializable | ||
臟讀 | Yes | No | No | No | ||
非可重復(fù)性讀取 | Yes | Yes | No | No | ||
幻讀 | Yes | Yes | Yes | No |
從上表可以看出隔離方式除了Any之外,一級比一級嚴(yán)厲。Any是一脈相承的,如果它沒有可繼承的,它將是最嚴(yán)厲的Serializable
事務(wù)的實(shí)現(xiàn)會給我們編程帶來什么樣的阻力?
1) 指定了TransactionFlow(TransactionFlowOption.Mandatory),而Binding卻沒有設(shè)置TransactionFlow為true 此時會出現(xiàn)類似"Bank"協(xié)定上至少有一個操作配置為將 TransactionFlowAttribute 屬性設(shè)置為"強(qiáng)制",但是通道的綁定"WSDualHttpBinding"未使用 TransactionFlowBindingElement 進(jìn)行配置。沒有 TransactionFlowBindingElement,無法使用設(shè)置為"強(qiáng)制"的 TransactionFlowAttribute 屬性。這樣的錯誤提示。
2) 設(shè)置了[OperationBehavior(TransactionScopeRequired=true)]的操作,卻沒有在TransactionScorp中執(zhí)行,會發(fā)生類似"服務(wù)操作需要事務(wù)成為流"的異常,截圖如下:
3) 也許上面兩個問題都是不是問題的問題,那這一點(diǎn)的確是需要我們研發(fā)人員注意的,否則我們會吃虧不少。這點(diǎn)涉及到事務(wù)和服務(wù)實(shí)例模式的聯(lián)系,我們通過學(xué)習(xí)WCF從理論到實(shí)踐:實(shí)例模式和對象生命周期 我們都學(xué)習(xí)到了實(shí)例在PerSession或者Single模式下不會每次都創(chuàng)建和消亡,這的確是一個不爭的真理,可在這里卻受到了挑戰(zhàn),不信你可以編寫一個程序,即使用你最放心的Single模式,那時不是就是說服務(wù)實(shí)例是一次創(chuàng)建,終身受用呢?下面就看看我第一次編寫范例程序后得到的運(yùn)行結(jié)果,我如下定義Bank
可在調(diào)用的時候,我卻發(fā)現(xiàn)了一個很奇怪的問題,按照理論來說,Bank服務(wù)實(shí)例應(yīng)該只創(chuàng)建一次,可運(yùn)行的截圖卻是如下:
這個結(jié)果是不是令大家大失所望呢?這是因為實(shí)現(xiàn)了事務(wù)的得服務(wù)還要受到TransactionAutoCompleteOnSessionClose的限制,該屬性默認(rèn)情況是true,它指示W(wǎng)CF在事務(wù)操作完成之后強(qiáng)制銷毀服務(wù)實(shí)例,相當(dāng)于調(diào)用服務(wù)的Dispose()方法進(jìn)行釋放,盡管是PerSession或者Single都難逃它的法網(wǎng)。如果想維持實(shí)例模式,可以將其設(shè)置為false,更改后運(yùn)行效果便可如期望一致效果圖不再給出。
4) 本文更多的實(shí)現(xiàn)了分布式任務(wù),分布式任務(wù)要使用TransactionScrop這個類,有關(guān)它的一些注意事項可以參考我以前的這篇文章:兩種實(shí)現(xiàn)事務(wù)方法的比較
一筆帶過,WCF是如何實(shí)現(xiàn)分布式事務(wù)的?
WCF實(shí)現(xiàn)事務(wù)的依據(jù)是基于WS-AtomicTransaction標(biāo)準(zhǔn),比較底層的東西,應(yīng)該屬于XXX內(nèi)幕系列,本文不作詳細(xì)闡述,如有興趣,可以查看園子中Kevin Li 兄弟的幾篇文章,我列在下面,希望Kevin Li不要見怪
1) 基于WS-AtomicTransaction標(biāo)準(zhǔn)的WCF遠(yuǎn)程分布式事務(wù)(一)
2) 基于WS-AtomicTransaction標(biāo)準(zhǔn)的WCF遠(yuǎn)程分布式事務(wù)(二)
3) 基于WS-AtomicTransaction標(biāo)準(zhǔn)的WCF遠(yuǎn)程分布式事務(wù)(補(bǔ)充)
代碼不騙人,用一個銀行存取款的范例來演練WCF事務(wù)
制作了一個小范例,用于演示事務(wù)的實(shí)現(xiàn),示例的情形如下
存在兩個服務(wù):1)IATMServer:它是模擬銀行的ATM機(jī)器的服務(wù) 2)IBank,它模擬銀行的賬戶服務(wù)。建立一個客戶端用于模擬ATM機(jī),我們的操作步驟如下:
1) 插卡
2) 存款
3) 取款
4) 拔卡
操作比較簡單,不做贅述,需要注意的是當(dāng)取款的時候,如果取款金額大于余額的時候,系統(tǒng)會抱錯,而賬戶余額不會更改。運(yùn)行效果圖
項目源文件: /Files/jillzhang/Jillzhang.Wcf.DistributedTranscations.rar
參考資料
1) http://www.rainsts.NET/article.ASP?id=479
2) http://blog.csdn.NET/honkerhero/archive/2007/03/30/1546429.ASPx
3) http://www.rainsts.NET/article.ASP?id=443
NET技術(shù):WCF從理論到實(shí)踐(12):事務(wù),轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。