你是否真正了解TransactionScope?
相關文章
將不確定變為確定~transactionscope何時提升為分布式事務
將不確定變為確定~transactionscope何時提升為分布式事務~續
將不確定變為確定~transactionscope何時提升為分布式事務~再續(避免引起不必要的MSDTC)
一 了解事務選項,用它來控制嵌套事務
public enum TransactionScopeOption { //如果存在環境事務(我認為應該叫嵌套事務,氛圍事務,ambient transaction),那么就加入其中,
如果不存在就創建新事務。如果加入事務那么只有在環境事務提交后才算提交。 Required = 0, //這個事務范圍將創建自己的事務,不會加入到當前外部事務中 RequiresNew=1, // 如果處於當前活動事務范圍內,那么這個事務范圍既不會加入氛圍事務 (ambient transaction),也不會創建自己的事務。
當部分代碼需要留在事務外部時,可以使用該選項。 Suppress = 2, }
二 何時會提升為分布式事務(何時發起MSDTC請求)
當你的WEB服務器與數據庫服務器在同台電腦上,對同一個庫進行操作時,它不會提升為分布式事務
當你的WEB服務器與數據庫服務器在同台電腦上,對於同一個庫,建立多個數據上下文時,它不會提升為分布式事務
當你的WEB服務器與數據庫服務器在同台電腦上,當你操作兩個庫的表,這時才會提升為分布式事
當你的WEB服務器與數據庫服務器不在同台電腦上,如果建立多於一個Connection連接,將會發起MSDTC
三 反映到linq to sql中,對於一個數據上下文,由於我們操作不當,也會產生多個Connection連接
這個方法本身沒有問題,做一件事件,而且職責很明確,當完成事情后,通過base.SubmitChange()方法提交到數據庫,這時,建立了connection,發送了sql語句,完成了這個通訊。
但有時,這種DAL層的動作需要被BLL層的業務進行組合,BLL層可以在一個事務范圍內調用多個類似的DAL方法,這時它們會把這種方法當成是分別獨立的工作單元,這是我們不希望看到的,因為在我們理解中,一個BLL業務應該是一個工作單元才對,返回到代碼中應該是,多個DAL層的方法被解釋為SQL語句后,提交一次就OK,所以,上面的代碼在進行組合后,可能會產生一些壞味道!
解決方法:
向BLL層開放數據上下文的SubmitChanges()方法及是否提交的屬性IsSubmitChange,在BLL層統一做提交,而對於DAL層的獨立的方法,在進行submitChanges()時,需要進行判斷IsSubmitChange是否為true,如果是,然后再提交,當然這個IsSubmitChange默認為true,即每次調用單獨的方法都會完成這個提交,這是正常的,也符合操作的完整性,
而在BLL進行組合方法時,先將必IsSubmitChange設為false,這時,DAL的方法將不會被提交,等待BLL的Submitchange()。
核心代碼:
提交屬性IsSubmitChange屬性默認為true
而對於BLL層,我們公開一個統一的操作對象,它會覆蓋掉基類的SubmitChanges方法,它的方法修飾符為public,對BLL層公開。
BLL層的基類BLLBase,可以通過架造方法為IsSutmitChange屬性賦值
OK,到這里,我們的BLL無論是調用BLL其它業務組合,還是調用DAL層方法組合,都可以控制代碼何時去提交到數據庫了,對於一個業務對象,就應該是一個工作單元,呵呵。