事務嵌套TransactionScope詳解


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因為不存在事務嵌套,所以使用不同的數據連接時,都可以成功,但是使用相同的數據連接,提交會出錯因為相同的數據鏈接,相同事務,錯誤數據也會一同提交,所以會在記錄日志時產生異常,導致不能記錄日志。

 

歡迎各位童鞋討論,個人愚見哈!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM