最近發現微軟自帶的TransactionScope(.Net Framework 2之后)是個好東東,提供的功能也很強大。
首先說說TransactionScope是什么,並能為我們做什么事情。其實看Transaction(事務)這個單詞,我想大家已經能猜到個大概。不同於SqlTransaction的事務,因為現在做的項目都有不同的分層架構,如果不在數據庫操作層里面做的話,那么使用TransactionScope是一種理想的方式,它是一個輕量級的事務類。所謂事務,就好比兩個串聯的開關,控制着一個燈泡,這兩個開關可以理解為一個獨立的單位,要么都開,否則燈泡就亮不起來。在程序里面就是要么都正常執行,如果中間有異常,事務就會出現回滾操作。回滾操作相當於回到操作之前的狀態,可以理解為沒有操作。這里面,事務是針對數據庫的一種行為。
要想使用TransactionScope,很方便,只需要在項目中添加System.Transactions.dll引用,然后添加命名空間(using System.Transactions;)即可。
我們來看看微軟的TransactionScope類:
public sealed class TransactionScope : IDisposable { public TransactionScope(); public TransactionScope(Transaction transactionToUse); public TransactionScope(TransactionScopeOption scopeOption); public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout); public TransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout); public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions); public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout, EnterpriseServicesInteropOption interopOption); public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption); public void Complete(); public void Dispose(); }
sealed關鍵字修飾類,說明該類不能被繼承。該類提供多種構造函數及Complete()和Dispose()方法.
=》Complete()即為提交事件的方法
=》Dispose()即釋放事務對象的方法
(1)TransactionScopeOption參數,該參數是一個枚舉類型:
public enum TransactionScopeOption { Required = 0, RequiresNew = 1, Suppress = 2 }
Required=》該范圍需要一個事務。 如果已經存在事務,則使用該事務。
否則,在進入范圍之前創建新的事務。 這是默認值。
RequiresNew=》總是為該范圍創建新事務
Suppress=》事務上下文在創建范圍時被取消。 范圍中的所有操作都在無事務上下文的情況下完成。
通過查看 System.Transactions.Transaction.Current 屬性。如果這個屬性為“null”,說明不存在當前事務。
(2)TransactionOptions參數,包含指定事務行為的附加信息。
public struct TransactionOptions { 。。。。。。 public IsolationLevel IsolationLevel { get; set; } public TimeSpan Timeout { get; set; } }
如果要修改 TransactionScope 的默認設置,可以實例化TransactionOptions對象,並對該對象傳遞需要的參數。可以通過它在 TransactionScope 對象上設置隔離級別和事務的超時時間。
IsolationLevel=》設置隔離級別
Serializable 可以在事務期間讀取可變數據,但是不可以修改,也不可以添加任何新數據。
RepeatableRead 可以在事務期間讀取可變數據,但是不可以修改。 可以在事務期間添加新數據。
ReadCommitted 不可以在事務期間讀取可變數據,但是可以修改它。
ReadUncommitted 可以在事務期間讀取和修改可變數據。
Snapshot 可以讀取可變數據。在事務修改數據之前,它驗證在它最初讀取數據之后另一個事務是否更改過這些數據。如果數據已被更新,則會引發錯誤。這樣使事務可獲取先前提交的數據值。在嘗試提升以此隔離級別創建的事務時,將引發一個InvalidOperationException,並產生錯誤信息“Transactions with IsolationLevel Snapshot cannot be promoted”(無法提升具有 IsolationLevel 快照的事務)。
Chaos 無法覆蓋隔離級別更高的事務中的掛起的更改。
Unspecified 正在使用與指定隔離級別不同的隔離級別,但是無法確定該級別。如果設置了此值,則會引發異常。
Timeout=》設置事務的超時時間(默認設置為 1 分鍾)
TimeSpan(Int64) 將新的 TimeSpan 初始化為指定的刻度數。
TimeSpan(Int32, Int32, Int32) 將新的 TimeSpan 初始化為指定的小時數、分鍾數和秒數。
TimeSpan(Int32, Int32, Int32, Int32) 將新的 TimeSpan 初始化為指定的天數、小時數、分鍾數和秒數。
TimeSpan(Int32, Int32, Int32, Int32, Int32) 將新的 TimeSpan 初始化為指定的天數、小時數、分鍾數、秒數和毫秒數。
(3)下面舉一個例子說明怎么使用,主要看紅色部分的代碼,紅色部分代碼即為使用TransactionScope的例子。用很少的幾行代碼就可以實現輕量級TransactionScope事務。
public void FixProjectSorceInsert() { TransactionOptions transactionOption = new TransactionOptions(); //設置事務隔離級別 transactionOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; // 設置事務超時時間為120秒 transactionOption.Timeout = new TimeSpan(0, 0, 120); using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOption)) { try { Insert(); Update(); Delete(); // 沒有錯誤,提交事務 scope.Complete(); } catch (Exception ex) { throw new Exception("發送信息異常,原因:" + ex.Message); } finally { //釋放資源 scope.Dispose(); } } }
(4)小結:使用事務,就像使用一把鎖,會鎖定資源。資源總是有限,所以進入和退出事務都要控制在較短的時間。在需要使用事務前創建它,在需要執行時打開連接,並盡快完成釋放事務。而且在事務執行中,盡可能避免執行不必要或與數據庫操作無關的代碼,因為這能夠防止資源被過度鎖定。