.NET事務應用原則 1.在同一個資料庫內進行CRUD時,應使用同一個DbConnection對象,且顯式指定DbConnection均為同一個DbTransaction,示例代碼如下: //在同一個DB中操作一個表時,可以不用顯式指定事務,因為單條SQL命令就是一個最小的事務單元 using (D
.NET事務應用原則
1.在同一個資料庫內進行CRUD時,應使用同一個DbConnection對象,且顯式指定DbConnection均為同一個DbTransaction,示例代碼如下:
//在同一個DB中操作一個表時,可以不用顯式指定事務,因為單條SQL命令就是一個最小的事務單元 using (DbConnection conn = new SqlConnection("資料庫連接字元串")) { var cmd = conn.CreateCommand(); cmd.CommandText = "delete users"; cmd.ExecuteNonQuery(); } //在同一個DB中操作多個表或執行不同的SQL命令時,需要顯式指定事務,且需確保每個Command均與同一個DbTransaction關聯 using (DbConnection conn = new SqlConnection("資料庫連接字元串")) { DbTransaction tran = conn.BeginTransaction(); try { var cmd = conn.CreateCommand(); cmd.Transaction = tran; cmd.CommandText = "delete users"; cmd.ExecuteNonQuery(); var cmd2 = conn.CreateCommand(); cmd2.Transaction = tran; cmd2.CommandText = "delete roles"; cmd2.ExecuteNonQuery(); tran.Commit(); } catch (Exception ex) { Console.WriteLine(ex.Message); tran.Rollback(); } }
2.在同一個伺服器上的不同資料庫之間進行CRUD時,應使用同一個DbConnection對象,且顯式指定DbConnection均為同一個DbTransaction,同時SQL命令語句中的包含的對象(表、視圖、存儲過程、函數等)應顯式指定資料庫名稱,格式如:databasename.owner.tablename,如:Db1.dbo.Users;Db2.dbo.Users;(前提條件:多個資料庫的用戶名及密碼相同的情況下,否則就只能使用分散式事務),示例代碼如下:
//在同一個Server不同的DB中操作多個表或執行不同的SQL命令時,需要顯式指定事務,且需確保每個Command均與同一個DbTransaction關聯,CommandText還應顯式添加資料庫名稱 using (DbConnection conn = new SqlConnection("資料庫連接字元串")) { DbTransaction tran = conn.BeginTransaction(); try { var cmd = conn.CreateCommand(); cmd.Transaction = tran; cmd.CommandText = "delete db1.dbo.users"; cmd.ExecuteNonQuery(); var cmd2 = conn.CreateCommand(); cmd2.Transaction = tran; cmd2.CommandText = "delete db2.dbo.roles"; cmd2.ExecuteNonQuery(); tran.Commit(); } catch (Exception ex) { Console.WriteLine(ex.Message); tran.Rollback(); } }
3.在不同的DB伺服器上進行CRUD時,應使用分散式事務,可以採取隱式或顯式開啟分散式事務,示例代碼如下:
//採用隱式開啟分散式事務 using (TransactionScope tranScope = new TransactionScope(TransactionScopeOption.RequiresNew)) { using (DbConnection conn = new SqlConnection("資料庫連接字元串")) { conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandText = "delete users"; cmd.ExecuteNonQuery(); } using (DbConnection conn2 = new SqlConnection("資料庫連接字元串2")) { conn2.Open(); var cmd2 = conn2.CreateCommand(); cmd2.CommandText = "delete users"; cmd2.ExecuteNonQuery(); } } //採用顯式開啟分散式事務 using (CommittableTransaction committableTransaction = new CommittableTransaction()) { try { using (DbConnection conn = new SqlConnection("資料庫連接字元串")) { conn.Open(); conn.EnlistTransaction(committableTransaction); //將連接登記到可提交事務 var cmd = conn.CreateCommand(); cmd.CommandText = "delete users"; cmd.ExecuteNonQuery(); } using (DbConnection conn2 = new SqlConnection("資料庫連接字元串2")) { conn2.Open(); conn2.EnlistTransaction(committableTransaction); //將連接登記到可提交事務 var cmd2 = conn2.CreateCommand(); cmd2.CommandText = "delete users"; cmd2.ExecuteNonQuery(); } committableTransaction.Commit(); } catch (Exception ex) { committableTransaction.Rollback(ex); } } //採用顯式開啟分散式事務,模擬TransactionScope用法的過程 { Transaction originalTransaction = Transaction.Current; //記錄當前的環境事務,用於後面的恢復 CommittableTransaction committableTransaction = null; DependentTransaction dependentTransaction = null; committableTransaction = new CommittableTransaction(); Transaction.Current = committableTransaction;//將定義的可提交事務作為當前的環境事務 try { using (DbConnection conn = new SqlConnection("資料庫連接字元串")) { conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandText = "delete users"; cmd.ExecuteNonQuery(); } dependentTransaction = Transaction.Current.DependentClone(DependentCloneOption.RollbackIfNotComplete); //複製當前的環境事務從而產生新的依賴事務,且指定必需等到該事務完成 Transaction.Current = dependentTransaction;//將複製到的新的依賴事務 using (DbConnection conn2 = new SqlConnection("資料庫連接字元串2")) { conn2.Open(); var cmd2 = conn2.CreateCommand(); cmd2.CommandText = "delete users"; cmd2.ExecuteNonQuery(); } } catch (Exception ex) { Transaction.Current.Rollback(ex); } finally //不論成功與否,最終都將恢覆成原來的環境事務 { Transaction transaction = Transaction.Current; Transaction.Current = originalTransaction; transaction.Dispose(); } }
最終總結一下:
1.查詢無需事務;
2.涉汲執行增、刪、改的SQL命令時,應考慮是否需要確保執行數據的一致性,若需要則必需使用事務,否則可以採取預設方式;
3.在同一個DB伺服器中,儘可能的使用本地事務,跨多個DB伺服器中,需要使用分散式事務;
4.儘可能的縮小事務的使用範圍,避免出現多層級的嵌套事務;
5.若需要使用分散式事務,在WINDOWS下需要開啟MS DTC服務(分散式事務管理器)