2017-07-30 59 views
1

我知道的解決方案,以實現在.NET C#SQL Server事務與「使用」關鍵字,並用這樣的代碼:什麼是傳遞一個SQL Server事務作爲參數的最佳方式

InsertDetails() 
{ 
    using (TransactionScope ts = new TransactionScope()) 
    {  
     InsertName();//SQL functions to insert name into name table 
     Insertaddress();//SQL functions to insert address into address table 
     InsertPhoneNo();//SQL functions to insert phone number into contact table 

     ts.Complete();  
    }  
} 

但是舉例來說,我希望將sql服務器事務作爲參數傳遞給不同的數據庫查詢的許多不同函數,而無需使用using語句示例。

在調用代碼路徑中的所有函數後,我想調用提交數據,如果出現問題,則執行回滾。

僞代碼看起來像這樣

InsertDetails() 
{ 
    var transaction = new Transaction(); 
    var sqlcon = new SqlConnection();  
     InsertName(transaction, sqlcon);//SQL functions to insert name into name table 
     Insertaddress(transaction, sqlcon);//SQL functions to insert address into address table 
     InsertPhoneNo(transaction, sqlcon);//code to insert phone no into contact table 
     try 
     { 
      ts.commit();  
     } 
     catch(Exception ex) 
     { 
      ts.rollback(); 
     } 
} 
+0

什麼阻止你這麼做? (當然,除了重新發明輪子) – Steve

+0

那麼使用語法更安全以及將事務傳遞給方法的目的是什麼?它應該是透明的 – MickyD

回答

4

注意#1:TransactionScope可以升級使用MSDTC,所以使用SqlTransaction可以有利於避免這種行爲。

注意#2:當行/表鎖定過度時,TransactionScope默認會使用序列化隔離級別。所以你可能想在使用TransactionScope時改變這種行爲。詳情參見:Why is System.Transactions TransactionScope default Isolationlevel Serializable

使用的SqlTransaction

堅持你的僞代碼示例中,我將重寫更是這樣的:

InsertDetails() 
{ 
    using (var sqlcon = new SqlConnection(<connectionString>)) 
    { 
     sqlcon.Open(); 

     // Create transaction to be used by all commands. 
     var transaction = sqlcon.BeginTransaction(); 

     try 
     { 
      InsertName(transaction, sqlcon);//SQL functions to insert name into name table 
      Insertaddress(transaction, sqlcon);//SQL functions to insert address into address table 
      InsertPhoneNo(transaction, sqlcon);//code to insert phone no into contact table 

      transaction.commit();  
     } 
     catch(Exception ex) 
     { 
      transaction.rollback(); 
      throw; 
     } 
    } 
} 

// Typical method implementation. 
private void InsertName(SqlTransaction transaction, SqlConnection sqlcon) 
{ 
    using (var cmd = sqlcon.CreateCommand()) 
    { 
     // This adds this command to the transaction. 
     cmd.Transaction = transaction; 

     // The rest is fairly typical. 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.CommandText = "InsertStoredProcedureName"; 
     ... set parameters etc. 
     cmd.ExecuteNonQuery(); 
     ... handle any OUTPUT parameters etc. 
    } 
} 

這將回滾事務的所有錯誤中的任何被調用的方法。

+0

不需要顯式調用回滾,不用調用commit就會使用using語句會導致回滾。如果你要在catch塊中明確地做到這一點,我會在回滾後添加一個'throw;',這樣異常就會冒出來。 –

+0

你會如何使用交易對象來進行粗查詢?有沒有可能有一個例子? – Dizzle

+0

@Dizzle - 修改後的代碼,以便在方法中顯示示例SqlTransaction用法。每種方法都需要以類似的方式添加到事務中。 –

1

我不推薦這種方法。

如果你是using new TransactionScope那麼你只需要在一切都好的時候調用Complete。如果不是,那麼如果Complete沒有被調用,那麼所有的東西都會回滾。所以這種方式打破了傳遞交易的目的,不是嗎?我認爲這個語法更清晰。

如果您需要確定您是否在事務處理環境下運行,則可以調用Transaction.Current以獲取當前事務。

相關問題