相關文章
將不確定變為確定~transactionscope何時提升為分布式事務
將不確定變為確定~transactionscope何時提升為分布式事務~續
將不確定變為確定~transactionscope何時提升為分布式事務~再續(避免引起不必要的MSDTC)
對於transactionscope我在之前寫過兩篇文件,在上一篇文章中已經把它何時會觸發分布式事務寫的很清楚了,但實現上,對於原理上為何會產生MSDTC說的還不夠明白,所以,有必要再寫一篇終如何去避免不必要的MSDTC。
注意本篇文章是上一篇文章的繼續,主要說的是數據庫服務器與WWW服務器不在同一台電腦上的情況
前言
分布式事務它依賴於windows的一個服務MSDTC,只有WWW服務器上的MSDTC服務處於啟動狀態,我們才可以使用分布式事務,對於分布式事務官方這樣定義它:協調跨多個數據庫、消息隊列、文件系統等資源管理器的事務。
frameworks什么時候會認識我們的TransactionScope是分布式的
對於數據庫多表操作來說,它何時是分布式,要看你的事務中的connection會話的數量,如果是一次,它會認識你在操作一個數據庫,這當然不會引入MSDTC,但如果你是多個connection會話,它會認識你在操作多張表,這時它屬於分布式的范疇,同時會引起MSDTC。
為什么我們在項目中,對於操作同一個數據庫的多張表,總會產生MSDTC
這要看一個基礎問題,事實很多時候解決問題的方法都是從基礎知識入手了,你之所以會犯錯是因為你對基礎知識掌握不牢靠。
對於LINQ To SQL或者EF等ORM來說,它們會提供一個SubmitChanges,作用是打開connection,將操作內容提交到數據庫,關閉connection。
而我們為了代碼的精簡性,有時會有CURD操作進行封裝,這是正常的,為了維護代碼方便進行必要的封裝,是種面向對象的思想,但注意,當你insert操作之后,如果封裝了SubmitChange,這時系統會認識你是一次完成的connection動作,而在進行第二個insert操作時,這時,會有兩個connection會話了,而在TransactionScope范圍內,對於多個Connection的理解就是多個庫,所以系統肯定會把它提升為分布式事務,並啟用MSDTC去支持它,這是正常的,一切都很正常,而對於我們來說,不希望每個TransactionScope都產生MSDTC,所以,我們應該如何去應對,方法很容易,將CURD操作的方法進行重裝,加個參數isSubmit就可以了,代碼如下:
/// <summary> /// 插入操作 /// </summary> /// <typeparam name="TEntity">實體類型</typeparam> /// <param name="entity">實體</param> /// <param name="isSubmit">是否同時提交到數據庫,對於寫在transactionscope里的多條語句, /// 如果本語句不是最后一條,本值為false,即不立即提交到數據</param> public void Insert<TEntity>(TEntity entity, bool isSubmit) where TEntity : class { if (entity is EntityBase) (entity as EntityBase).OnInsertBefore(); //Logger.InfoLog("Create 表名:{0},內容:{1}", entity, ToJson(entity)); _db.Entry<TEntity>(entity); _db.Set<TEntity>().Add(entity); if (isSubmit) this.SaveChanges(); if (entity is EntityBase) (entity as EntityBase).OnInsertAfter(); }
對於具體的事務塊,代碼可能是這樣:
using (TransactionScope trans = new TransactionScope()) { try { base.Insert<Product_Comment>(entity.Product_Comment, false); base.Insert<Review>(entity.Review); trans.Complete(); } catch (Exception) { throw; } finally { trans.Dispose(); } }
對於一個SubmitChange()所產生的SQL代碼為:(一個connection會話)
對於多個SubmitChange()所產生的SQL代碼為:(多個connection會話)
總結:對於數據服務器與WWW服務器不在一起電腦上時,產生MSDTC的關鍵在於connection會話的數據,一個會話表示操作一個數據庫,這時不產生MSDTC,如果多個會話,認識是操作多個數據庫,所以就產生了MSTDC!小微真聰明!
感謝閱讀!
