將(jiang)不確定變為(wei)確定~transactionscope何時提升(sheng)為(wei)分布式事務(wu)~再續(避免引起不必要的MSDTC)
相關文章
將不確定變為確定~transactionscope何時提升為分布式事務
將不確定變為確定~transactionscope何時提升為分布式事務~續
將不確定變為確定~transactionscope何時提升為分布式事務~再續(避免引起不必要的MSDTC)
對于transactionscope我在之前寫過兩篇文件,在上一篇文章中已經把它(ta)何(he)(he)時會觸發分布式事務(wu)寫的(de)(de)很(hen)清楚(chu)了,但實現上,對于(yu)原理上為何(he)(he)會產生MSDTC說(shuo)的(de)(de)還不夠(gou)明(ming)白,所以,有必(bi)要再(zai)寫一篇終如何(he)(he)去避免不必(bi)要的(de)(de)MSDTC。
注意本篇文章是上一篇文章的繼續,主要說的是數據庫服務器與WWW服務器不在同一臺電腦上的情況
前言
分(fen)布式事務(wu)它依賴于windows的一(yi)個(ge)服務(wu)MSDTC,只(zhi)有(you)WWW服務(wu)器上的MSDTC服務(wu)處于啟(qi)動狀態,我們才(cai)可(ke)以使用(yong)分(fen)布式事務(wu),對于分(fen)布式事務(wu)官方這樣定義它:協(xie)調跨(kua)多個(ge)數據庫、消(xiao)息(xi)隊列、文件系統等資源(yuan)管理器的事務(wu)。
frameworks什么時候會認識我們的TransactionScope是分布式的
對于(yu)數(shu)據(ju)(ju)庫(ku)多表(biao)操(cao)作(zuo)(zuo)來說(shuo),它(ta)何時(shi)(shi)是(shi)分布式,要看你的事務中的connection會(hui)話(hua)的數(shu)量,如(ru)果是(shi)一次,它(ta)會(hui)認識(shi)你在操(cao)作(zuo)(zuo)一個數(shu)據(ju)(ju)庫(ku),這當然不會(hui)引(yin)入MSDTC,但如(ru)果你是(shi)多個connection會(hui)話(hua),它(ta)會(hui)認識(shi)你在操(cao)作(zuo)(zuo)多張(zhang)表(biao),這時(shi)(shi)它(ta)屬于(yu)分布式的范疇(chou),同時(shi)(shi)會(hui)引(yin)起MSDTC。
為什么我們在(zai)項(xiang)目(mu)中(zhong),對于操作同(tong)一個數據庫(ku)的多張表,總會產生MSDTC
這要看(kan)一個基(ji)礎問題,事實很(hen)多時候解決問題的方(fang)法都是從基(ji)礎知識(shi)入(ru)手了,你之所以會(hui)犯錯是因為你對(dui)基(ji)礎知識(shi)掌握(wo)不牢靠(kao)。
對(dui)于(yu)LINQ To SQL或者EF等ORM來說(shuo),它們會提(ti)供一個SubmitChanges,作用是打開(kai)connection,將操作內容提(ti)交(jiao)到數據庫,關閉connection。
而我們為了代碼的精簡性,有時會有CURD操作進行封裝,這是正常的,為了維護代碼方便進行必要的封裝,是種面向對象的思想,但注意,當你insert操作之后,如果封裝了SubmitChange,這時系統會認識你是一次完成的connection動作,而在進行第二個insert操作時,這時,會有兩個connection會話了,而在TransactionScope范圍內,對于多個Connection的理解就是多個庫,所以系統肯定會把它提升為分布式事務,并啟用MSDTC去(qu)支持它,這是(shi)正(zheng)常的(de),一(yi)切都很(hen)正(zheng)常,而對于我(wo)們來說(shuo),不希(xi)望每個TransactionScope都產生MSDTC,所(suo)以,我(wo)們應(ying)該如何去(qu)應(ying)對,方法(fa)很(hen)容易,將CURD操(cao)作的(de)方法(fa)進行(xing)重裝,加個參數isSubmit就可以了,代碼(ma)如下:
/// <summary> /// 插入操作 /// </summary> /// <typeparam name="TEntity">實體類型(xing)</typeparam> /// <param name="entity">實體(ti)</param> /// <param name="isSubmit">是否(fou)同時提交(jiao)到(dao)數據庫,對于(yu)寫(xie)在transactionscope里(li)的多條語句, /// 如果本語(yu)句不(bu)是最后一條(tiao),本值為false,即不(bu)立(li)即提交到數據</param> public void Insert<TEntity>(TEntity entity, bool isSubmit) where TEntity : class { if (entity is EntityBase) (entity as EntityBase).OnInsertBefore(); //Logger.InfoLog("Create 表名:{0},內(nei)容:{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(); }
對于具體的事務(wu)塊,代碼(ma)可能是這(zhe)樣(yang):
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(); } }
對(dui)于一(yi)個SubmitChange()所產生的(de)SQL代碼(ma)為:(一(yi)個connection會話)
對于多個SubmitChange()所產生的(de)SQL代碼為:(多個connection會話)
總結:對于數據服務器與WWW服務器不在一起電腦上時,產生MSDTC的關鍵在于connection會話的數據,一個會話表示操作一個數據庫,這時不產生MSDTC,如果多個會話,認識是操作多個數據庫,所以就產生了MSTDC!小微真聰明!
感謝閱讀!