微軟自帶的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 bool FixProjectSorceInsert()
{
bool result = true;
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);
result = false;
}
finally
{
//釋放資源
scope.Dispose();
}}
return result;
}
(4)小結:使用事務,就像使用一把鎖,會鎖定資源。資源總是有限,所以進入和退出事務都要控制在較短的時間。在需要使用事務前創建它,在需要執行時打開連接,並盡快完成釋放事務。而且在事務執行中,盡可能避免執行不必要或與數據庫操作無關的代碼,因為這能夠防止資源被過度鎖定。