TransactionScope的使用

本文導讀:在實際開發工作中,執行一個事件,然後調用另一接口插入數據,如果處理邏輯出現異常,那麼之前插入的數據將成爲垃圾數據,我們所希望的是能夠在整個這個方法定義爲一個事務,TransactionScope 類提供一個簡單方法,通過這一方法,您不必與事務本身交互,即可將代碼塊標記爲參與某個事務。TransactionScope對象創建了一個事務,同時將該事務設置給Transaction類的Current屬性。

一、TransactionScope的優點


1、使用起來比較方便.TransactionScope可以實現隱式的事務,使你可以在寫數據訪問層代碼的時候不用考慮到事務,而在業務層的控制事務.

2、可以實現分佈式事務,比如跨庫或MSMQ.

二、TransactionScope缺點

1、性價比不高.比如,你只是在"Scope"裏控制一個庫的事務.用"TransactionScope"就有點浪費了.
2、一般情況下只要你使用"TransactionScope",都要配置MSDTC,要配防火牆,要開139端口.這個端口不可以更改

三、如果你不得不用分佈式事務,那也得琢磨琢磨

1.這步操作一定得在事務當中嗎?這步操作如果沒完成或者失敗了,值得回滾整個事務嗎?難道沒有優雅的補償措施或者容錯措施?

2.分佈式事務涉及到的點,必須的這麼多?必須得實時的操作這一大串?不能通過通知類操作去精簡掉某些點?

3.在發起分佈式事務之後,你是不是做了事務無關的操作,儘管這些操作跟事務無關?(如,讀取數據、計算、等用戶返回消息、等其他模塊的調用返回等等)要知道事務應該儘快結束。

4.你沒有把一些讀操作也算在事務裏面了吧?這是很容易犯的錯誤,你在事務中Enlist了一個select 操作。

5.你的操作,某些步驟可以等全部操作完成之後再執行.這類操作具有明顯的通知類特點。通知類操作是說,我給你一個通知,並且我保證通知到了你;你必須吃下這個通知,並且保證處理成功,但是你不必我一通知你你就處理。這樣的操作很明顯可以用另外一個任務去搞。

四、使用分佈式事務注意如下幾點

1:確保參與事務的machine開啓了分佈式事務支持;

2:如果machine開啓了防火牆,需要設置msdtc進程爲例外;

3:參與事務的machine不能跨域(如果跨域,目前微軟還沒有確切的解決方案);

4:多數據庫時才使用分佈式事務,如果是同一個數據庫,最好使用SqlTransaction.

五、TransactionScope事務級別

在TransactionScope中默認的事務級別是Serializable,即在事務過程中,完全性鎖表。別的進程不能查詢,修改,新增,刪除。這樣會導致效率大大降低,雖然數據完整性很高。通常我們不需要那麼高的數據完整性。所以需要修改默認的事務級別:

所有的事務級別如下


Chaos

無法改寫隔離級別更高的事務中的掛起的更改。


ReadCommitted

不可以在事務期間讀取可變數據,但是可以修改它。


ReadUncommitted

可以在事務期間讀取和修改可變數據。

RepeatableRead

可以在事務期間讀取可變數據,但是不可以修改。可以在事務期間添加新數據。

Serializable

可以在事務期間讀取可變數據,但是不可以修改,也不可以添加任何新數據。
Snapshot

可以讀取可變數據。在事務修改數據之前,它驗證在它最初讀取數據之後另一個事務是否更改過這些數據。如果數據已被更新,則會引發錯誤。這樣使事務可獲取先前提交的數據值。

在嘗試提升以此隔離級別創建的事務時,將引發一個 InvalidOperationException,併產生錯誤信息“Transactions with IsolationLevel Snapshot cannot be promoted”(無法提升具有 IsolationLevel 快照的事務)。
Unspecified

正在使用與指定隔離級別不同的隔離級別,但是無法確定該級別。如果設置了此值,則會引發異常。

 六、在C#中使用TransactionScope類(分佈式事務),則須注意如下事項

1、在項目中引用using System.Transactions命名空間(先要在添加net組件的引用);

2、對MSDTC組件設置:

在控制面板--->管理工具--->服務 中,開啓Distributed Transaction Coordinator 服務。

a、控制面板->管理工具->組件服務->計算機->我的電腦->右鍵->屬性
b、選擇MSDTC頁, 確認"使用本地協調器"
c、點擊下方"安全配置"按鈕
d、勾選: "允許網絡DTC訪問","允許遠程客戶端","允許入站","允許出站","不要求進行身份驗證".
e、對於數據庫服務器端, 可選擇"要求對呼叫方驗證"
f、勾選:"啓用事務Internet協議(TIP)事務"。
g、在雙方防火牆中增加MSDTC.exe例外
可用命令行: netsh firewall set allowedprogram %windir%/system32/msdtc.exe MSDTC enable

3、重啓IIS服務器。

注意:

我們只要確保數據庫的打開操作是在事務範圍內打開就行了。這樣就可以做到事務的正確操作。

如果WEB服務器和數據庫是在同一臺服務器上,TransactionScope使用的是本地事務,這時不需要配置MSDTC。

如果WEB服務器和數據庫不在同一臺服務器上,TransactionScope會自動提升事務級別爲分佈式事務,這時就需要配置MSDTC。

七、TransactionScope實例

//// <summary>        /// 發送消息         /// </summary>        /// <param name="sendUserId"></param>        /// <param name="toUser">格式7FFA3AF2-E74B-4174-8403-5010C53E49A7|userName,7FFA3AF2-E74B-4174-8403-5010C53E49A7|userName</param>        /// <param name="content"></param>        /// <param name="sendedStatus">表示已送</param>        /// <returns></returns>        public static int sendMessage(string sendUserId, string toUser, string content, string sendedStatus)        {           
            int receiveCount = 0;            TransactionOptions transactionOption = new TransactionOptions();            //設置事務隔離級別            transactionOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;            // 設置事務超時時間爲60秒            transactionOption.Timeout = new TimeSpan(0, 0, 60);            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOption))            {                try                {                    //在這裏實現事務性工作     //發送消息                    insertMessage(sendUserId, toUser, content, sendedStatus);     //在接收信息表中插入記錄                    receiveCount += insertReceiveMessage(userids[0], sendUserId, content, "0");                                       // 沒有錯誤,提交事務                    scope.Complete();                }                catch (Exception ex) {                    throw new Exception("發送信息異常,原因:"+ex.Message);                }finally{                    //釋放資源                    scope.Dispose();                  }                                           }            return receiveCount;        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章