日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

EntityFramework與TransactionScope事務(wù)和并發(fā)控制

 昵稱10504424 2013-09-11

EntityFramework與TransactionScope事務(wù)和并發(fā)控制

最近在園子里看到一篇關(guān)于TransactionScope的文章,發(fā)現(xiàn)事務(wù)和并發(fā)控制是新接觸Entity Framework和Transaction Scope的園友們不易理解的問題,遂組織此文跟大家共同探討。

首先事務(wù)的ACID特性作為最基礎(chǔ)的知識(shí)我想大家都應(yīng)該知道了。ADO.NET的SQLTransaction就是.NET框架下訪問SqlServer時(shí)最底層的數(shù)據(jù)庫事務(wù)對(duì)象,它可以用來將多次的數(shù)據(jù)庫訪問封裝為“原子操作”,也可以通過修改隔離級(jí)別來控制并發(fā)時(shí)的行為。TransactionScope則是為了在分布式數(shù)據(jù)節(jié)點(diǎn)上完成事務(wù)的工具,它經(jīng)常被用在業(yè)務(wù)邏輯層將多個(gè)數(shù)據(jù)庫操作組織成業(yè)務(wù)事務(wù)的場景,可以做到透明的可分布式事務(wù)控制和隱式失敗回滾。但與此同時(shí)也經(jīng)常有人提到TransactionScope有性能和部署方面的問題,關(guān)于這一點(diǎn),根據(jù)MSDN的 Using the TransactionScope Class 的說法,當(dāng)一個(gè)TransactionScope包含的操作是同一個(gè)數(shù)據(jù)庫連接時(shí),它的行為與SqlTransaction是類似的。當(dāng)它在多個(gè)數(shù)據(jù)庫連接上進(jìn)行數(shù)據(jù)操作時(shí),則會(huì)將本地?cái)?shù)據(jù)庫事務(wù)提升為分布式事務(wù),而這種提升要求各個(gè)節(jié)點(diǎn)均安裝并啟動(dòng)DTC服務(wù)來支持分布式事務(wù)的協(xié)調(diào)工作,它的性能與本地?cái)?shù)據(jù)庫事務(wù)相比會(huì)低很多,這也是CAP定律說的分布式系統(tǒng)的Consistency和Availability不可兼得的典型例子。所以當(dāng)我們選擇是否使用TransactionScope時(shí),一定要確認(rèn)它會(huì)不會(huì)導(dǎo)致不想發(fā)生的分布式事務(wù),也應(yīng)該確保事務(wù)盡快做完它該做的事情,為了確認(rèn)事務(wù)是否被提升我們可以用SQL Profiler去跟蹤相關(guān)的事件。

然后再來看一看Entity Framework,其實(shí)EF也跟事務(wù)有關(guān)系。它的Context概念來源于Unit of Work模式,Context記錄提交前的所有Entity變化,并在SaveChanges方法調(diào)用時(shí)發(fā)起真正的數(shù)據(jù)庫操作,SaveChanges方法在默認(rèn)情況下隱含一個(gè)事務(wù),并且試圖使用樂觀并發(fā)控制來提交數(shù)據(jù),但是為了進(jìn)行并發(fā)控制我們需要將Entity Property的ConcurrencyMode設(shè)置為Fixed才行,否則EF不理會(huì)在此Entity上面發(fā)生的并發(fā)修改,這一點(diǎn)可以參考MSDN Saving Changes and Managing Concurrency。微軟推薦大家使用以下方法來捕獲沖突的并發(fā)操作,并使用RefreshMode來選擇覆蓋或丟棄失敗的操作:

當(dāng)然除了樂觀并發(fā)控制我們還可以對(duì)沖突特別頻繁、沖突解決代價(jià)很大的用例進(jìn)行悲觀并發(fā)控制。悲觀并發(fā)基本思想是不讓數(shù)據(jù)被同時(shí)離線修改,也就是像源碼管理里面“加鎖”功能一樣,碼農(nóng)甲鎖上了這個(gè)文件,乙就不能再修改了,這樣一來這個(gè)文件就不可能發(fā)生沖突,悲觀并發(fā)控制實(shí)現(xiàn)的方式比如數(shù)據(jù)行加IsLocked字段等。

最后為了進(jìn)行多Context事務(wù),當(dāng)然還可以混合使用TransactionScope和EF。

好了理論簡單介紹完,下面的例子是幾種不同的方法對(duì)并發(fā)控制的效果,需求是每個(gè)Member都有個(gè)HasMessage字段,初始為False,我們需要給其中一個(gè)Member加入唯一一條MemberMessage,并將Member.HasMessage置為True。

建庫腳本:

方法1:不使用TransactionScope,只依賴Entity各字段的默認(rèn)并發(fā)控制。

Context和Entity定義

測試代碼

同時(shí)運(yùn)行兩個(gè)程序,結(jié)果是無法確保不重復(fù)插入

 

通過分析不難發(fā)現(xiàn),該場景的并發(fā)控制關(guān)鍵就在于插入前檢查HasMessage如果是False,則插入MemberMessage后更新Member.HasMessage字段時(shí)需要再次檢查數(shù)據(jù)庫中HasMessage字段是否為False,如果為True就是有其他人并發(fā)的更改了該字段,本次保存應(yīng)該回滾或做其他處理。所以為此需要有針對(duì)性的加入并發(fā)控制。

方法2:給HasMessage字段加上并發(fā)檢查

仍然使用方法1的測試代碼,結(jié)果則是其中一次數(shù)據(jù)插入會(huì)拋出OptimisticConcurrencyException,也就是說防止重復(fù)插入數(shù)據(jù)的目的已經(jīng)達(dá)到了。

 

那回過頭來看看是否可以使用TransactionScope對(duì)EF進(jìn)行并發(fā)控制,于是有方法3:使用TransactionScope但不給Entity加入并發(fā)檢查

Context和Entity的定義與方法1完全一致,測試代碼為

同樣啟動(dòng)兩個(gè)程序測試,發(fā)現(xiàn)其中一次保存操作拋出DbUpdateException,其內(nèi)部原因是Transaction死鎖導(dǎo)致該操作被作為犧牲者。所以看起來也可以達(dá)到并發(fā)控制的效果,這種方式的優(yōu)點(diǎn)是不需要去仔細(xì)辨別業(yè)務(wù)中哪些操作會(huì)導(dǎo)致字段的并發(fā)更新沖突,所有的Entity都可以不加ConcurrencyCheck,缺點(diǎn)則是當(dāng)沖突不多的時(shí)候這種死鎖競爭協(xié)調(diào)與樂觀并發(fā)控制相比性能會(huì)低些。

最后為了完備測試各種組合,我們?cè)囈辉?strong>方法4:既使用TransactionScope,又在HasMessage字段上加入ConcurrencyCheck,Entity代碼參考方法1,測試代碼則參考方法3,結(jié)果仍然是TransactionScope檢測到死鎖并選擇其中一個(gè)競爭者拋出異常。

 

結(jié)論:

  1. TransactionScope用或不用主要取決于是否需要進(jìn)行分布式事務(wù)
  2. 即使不需要分布式事務(wù),TransactionScope也可以用于沒有精力仔細(xì)分析哪些Entity的字段需要進(jìn)行并發(fā)檢查的時(shí)候
  3. 如果能夠細(xì)粒度分析并發(fā)場景,則推薦使用EF自帶的并發(fā)控制機(jī)制

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多