將不確定變為確定~transactionscope何時提升為分布式事務~再續(避免引起不必要的MSDTC)


回到目錄

相關文章

將不確定變為確定~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!小微真聰明!

感謝閱讀!

回到目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM