TransactionScope 分情境使用才可以
System.Transactions 基礎結構既提供了基於 Transaction 類的顯式編程模型,也提供了使用 TransactionScope 類的隱式編程模型,在後一種模型中,事務由該基礎結構自動管理。
重要說明: |
建議使用 TransactionScope 類建立隱含交易,以便自動為您管理環境事務上下文。對於需要跨多個函數調用或多個線程調用使用相同事務的應用程式,您還應該使用 TransactionScope 和 DependentTransaction 類。有關此模型的更多資訊,請參見使用事務範圍實現隱含交易 主題。有關編寫事務性應用程式的更多資訊,請參見編寫事務應用程式。 |
在通過 new 語句執行個體化 TransactionScope 時,交易管理員將確定要參與哪個事務。一經確定,此範圍將始終參與該事務。此決策基於兩個因素:是否存在環境事務以及建構函式中 TransactionScopeOption 參數的值。 環境事務是在其中執行您的代碼的事務。通過調用 Transaction 類的 Current 靜態屬性可擷取對環境事務的引用。有關如何使用此參數的更多資訊,請參見 使用事務範圍實現隱含交易 主題的“事務流管理”一節。
如果在事務範圍中(即從初始化 TransactionScope 對象到調用其 Dispose 方法之間)未發生異常,則允許該範圍所參與的事務繼續。如果事務範圍中的確發生了異常,它所參與的事務將復原。
當應用程式完成它要在一個事務中執行的所有工作以後,您應當只調用 Complete 方法一次,以通知交易管理員可以接受提交事務。未能調用此方法將中止該事務。
對 Dispose 方法的調用標誌著該事務範圍的結束。在調用此方法之後發生的異常不會影響該事務。
如果在範圍中修改 Current 的值,則會在調用 Dispose 時引發異常。但是,在該範圍結束時,先前的值將被還原。此外,如果在建立事務的事務範圍內對 Current 調用 Dispose,則該事務將在相應範圍末尾處中止。
一、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執行個體
C# 代碼 複製
/**//// <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; }
類似執行個體:
//修改訂單狀態 protected void UpdateState_Click(object sender, EventArgs e) { string id = Request.QueryString["id"]; int x; if (int.TryParse(id, out x)) { DAL.OrderDAO orderdao = new DAL.OrderDAO(); Model.Order od = orderdao.GetModel(x); if (od!=null) { switch (od.state) { case 0: if (chkState.Items[1].Selected == true) { orderdao.UpdateState(od.id, 1); Utility.Tool.alert("狀態更新成功",Request.Url.ToString(),this.Page); } else { Utility.Tool.alert("請勾選使用者已經划出款", this.Page); return; } break; case 3: if (chkState.Items[4].Selected == true) { //這裡完成訂單,給使用者增加積分,我們用事務來處理 using (TransactionScope scope=new TransactionScope()) { try { orderdao.UpdateState(od.id, 4); //把訂單中的商品金額,增加到使用者的積分。 int jifen = Convert.ToInt16(od.detailsmoney); new DAL.UserDAO().UpdateIntegral(User.Identity.Name, jifen); Utility.Tool.alert("狀態更新成功,積分 " + jifen + " 分已經發送",
Request.Url.ToString(), this.Page); //處理完事務之後,記得提交,不然,他還是不執行的 scope.Complete(); } catch (Exception re) { Response.Write("事務錯誤,請聯絡管理員"+re.Message); Response.End(); } } } else { Utility.Tool.alert("請勾選使用者已經收到貨", this.Page); return; } break; default: break; } } } }
與其它類型事務比較
1、SQL事務
優點:執行效率最佳
限制:事務上下文僅在資料庫中調用,難以實現複雜的商務邏輯。
[sql] view plain copy