using(TransactionScope scope1 = new TransactionScope()) //Default is Required { using(TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Required)) { ... } using(TransactionScope scope3 = new TransactionScope(TransactionScopeOption.RequiresNew)) { ... } using(TransactionScope scope4 = new TransactionScope(TransactionScopeOption.Suppress)) { ... } }
首先來看官方給出的解釋
使用 Required 創建了一個新范圍 (scope1)。范圍 scope1 是根范圍,因為它創建了一個新事務(事務 A),並使事務 A 成為環境事務。Scope1 后來又創建了三個對象,並用不同的 TransactionScopeOption 值對其中每個對象進行了實例化。例如,scope2 是用 Required 創建的;由於存在環境事務,因此該范圍聯接 scope1 所創建的第一個事務。請注意,scope3 是新事務的根范圍,而 scope4 則沒有環境事務。
再看試驗結果:
public string test(string str) { try { using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { Timeout = new TimeSpan(0, 5, 0), IsolationLevel = IsolationLevel.ReadUncommitted })) { Document_ASN_Header header = new Document_ASN_Header(); header.AddDate = DateTime.Now; header.AddWho = 1; header.OwnerID = 118; header.DocumentType = 8; header.DocumentStatus = 15; header.DocumentNo = str; db.Document_ASN_Header.InsertOnSubmit(header); db.SubmitChanges(); Document_ASN_Details details = new Document_ASN_Details(); details.CustomField1 = "!@#$%^&&*()"; details.AddDate = DateTime.Now; details.AddWho = 1; details.DocumentASNNo = str; details.SKUNO = "20100018";//20100018 try { DateTime dt = DateTime.Parse("2012*02-01"); } catch (Exception e) { insertLogError(new EDI_Log_Result() { RETMSG = e.Message }); return e.Message; } db.Document_ASN_Details.InsertOnSubmit(details); insertLogOk(new EDI_Log_Result() { RETMSG = "OK" }); db.SubmitChanges(); ts.Complete(); return "ok"; } } catch(Exception e) { insertLogError(new EDI_Log_Result() { RETMSG = e.Message }); return e.Message; } } private void insertLogError(EDI_Log_Result log) { HongTuDataContext logDB = new HongTuDataContext(); using (TransactionScope ts2 = new TransactionScope(TransactionScopeOption.Suppress, new TransactionOptions() { Timeout = new TimeSpan(0, 5, 0), IsolationLevel = IsolationLevel.ReadUncommitted })) { logDB.EDI_Log_Result.InsertOnSubmit(log); logDB.SubmitChanges(); ts2.Complete(); } } private void insertLogOk(EDI_Log_Result log) { using (TransactionScope ts3 = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { Timeout = new TimeSpan(0, 5, 0), IsolationLevel = IsolationLevel.ReadUncommitted })) { db.EDI_Log_Result.InsertOnSubmit(log); db.SubmitChanges(); ts3.Complete(); } }
大致的意思是往數據庫中插入一個Header和Details信息
如果SKUNO為空會導致SqlException
DateTime的轉換是一個驗證基礎數據的條件的一個模擬
把日志記錄分成了兩個方法
Error是記錄錯誤日志時所使用的方法,不相同的數據源鏈接
Ok是記錄正確日志所使用的方法,相同的數據鏈接
記錄DateTime轉換錯誤
使用Error方法(不相同的數據源鏈接)
TransactionScopeOption參數為Suppress與RequiresNew時能夠保存成功,返回該字符串未被識別為有效的 DateTime。
TransactionScopeOption參數為Required時建立分布式事務(在能建立分布式事務的前提條件下),結果未知,預測不能保存
個人理解:
因為采用不同的數據鏈接,而且參數為Suppress與RequiresNew,所以與ts事務是無關和同等地位的狀態,所以類似獨立事務,能夠保存
建立分布式事務,Required環境事務是ts但是,在此ts並沒有顯示提交,所以不能保存數據
使用Ok方法(相同的數據鏈接)
Required:無法保存數據庫,返回該字符串未被識別為有效的 DateTime。
RequiresNew:無法保存數據庫,返回連接當前已登記事務。請完成當前事務,然后重試。
Suppress:無法保存數據庫,返回該字符串未被識別為有效的 DateTime。
個人理解:
Required環境事務是ts但是,在此ts並沒有顯示提交,所以不能保存數據
Suppress雖然無環境事務,但是是統一數據連接,應當也是相同的事務ts但是,在此ts並沒有顯示提交,所以不能保存數據
RequiresNew就如提示所示,當前鏈接已經有未提交事務存在,所以不能提交新事務
記錄正確日志
使用Error方法(不相同的數據源鏈接)
Required:建立分布式事務(在能建立分布式事務的前提條件下),結果未知,預測能夠保存
RequiresNew:可以保存數據庫
Suppress:可以保存數據庫
個人理解:
因為采用不同的數據鏈接,而且參數為Suppress與RequiresNew,所以與ts事務是無關和同等地位的狀態,所以類似獨立事務,能夠保存
建立分布式事務,Required環境事務是ts但是,在此ts有顯示提交,所以可以保存數據
使用Ok方法(相同的數據鏈接)
Suppress:可以保存數據庫
RequiresNew:連接當前已登記事務。請完成當前事務,然后重試。
Required:可以保存數據庫
個人理解:
Required環境事務是ts且ts有顯示提交,所以可以保存數據
Suppress雖然無環境事務,但是是統一數據連接,應當也是相同的事務ts且在此ts有顯示提交,所以可以保存數據
RequiresNew就如提示所示,當前鏈接已經有未提交事務存在,所以不能提交新事務
最外層catch因為不存在事務嵌套,所以使用不同的數據連接時,都可以成功,但是使用相同的數據連接,提交會出錯因為相同的數據鏈接,相同事務,錯誤數據也會一同提交,所以會在記錄日志時產生異常,導致不能記錄日志。
歡迎各位童鞋討論,個人愚見哈!