2012-10-02 63 views

回答

2

我剛剛嘗試過如何升級到分佈式事務在SQL Server 2012(EXPRESS)中的行爲。我觀察到了與SQL Server 2008相同的行爲。

我已經用非常簡單的代碼與SqlConnection對象進行了測試。在一個事務範圍內總是有兩個數據庫訪問(INSERT)。

沒有嵌套連接 - 不升高

這是唯一的選擇,如果你想避免晉升爲DTC。在交易期間僅訪問一個持久資源(數據庫),並在打開另一個連接之前關閉一個連接。 (最終你能避免DT通過重複使用相同的連接,但是當你使用連接池,並且很可能會令你的代碼的可讀性,沒有必要。)

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB"; 

static void Main(string[] args) 
{ 
    using (var scope = new TransactionScope()) 
    { 
     using (var conn = new SqlConnection(connectionString)) 
     { 
      conn.Open(); 
      using (var command = conn.CreateCommand()) 
      { 
       command.CommandType = CommandType.Text; 
       command.CommandText = "INSERT INTO TestTable(Value) VALUES (@1)"; 
       command.Parameters.Add(new SqlParameter("1", "123456")); 
       command.ExecuteNonQuery(); 
      } 
     } 
     using (var conn2 = new SqlConnection(connectionString)) 
     { 
      conn2.Open(); 
      using (var command2 = conn2.CreateCommand()) 
      { 
       command2.CommandType = CommandType.Text; 
       command2.CommandText = "INSERT INTO TestTable(Value) VALUES (@1)"; 
       command2.Parameters.Add(new SqlParameter("1", "123456")); 
       command2.ExecuteNonQuery(); 
      } 
     } 
     scope.Complete(); 
    } 
} 

嵌套式連接 - 升級

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB"; 

static void Main(string[] args) 
{ 
    using (var scope = new TransactionScope()) 
    { 
     using (var conn = new SqlConnection(connectionString)) 
     { 
      conn.Open(); 
      // EXECUTE INSERT 
      using (var conn2 = new SqlConnection(connectionString)) 
      { 
       conn2.Open(); 
       // EXECUTE INSERT 
      } 
     }     
     scope.Complete(); 
    } 
} 

不嵌套連接訪問不同數據庫 - 升級

如果喲在交易過程中,您可以訪問兩個或更多的持久資源,並始終將其提升爲DTC。

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB"; 
static string connectionString2 = "data source=.\\;Integrated Security=SSPI;Database=TestDB2"; 

static void Main(string[] args) 
{ 
    using (var scope = new TransactionScope()) 
    { 
     using (var conn = new SqlConnection(connectionString)) 
     { 
      conn.Open(); 
      // EXECUTE INSERT 
     } 
     using (var conn2 = new SqlConnection(connectionString2)) 
     { 
      conn2.Open(); 
      // EXECUTE INSERT 
     } 
     scope.Complete(); 
    } 
} 

注意 這不要緊,你將執行什麼樣的CRUD操作的,它總是取決於以何種方式連接打開和關閉。

1

在@ mipe34的第三種情況(在同一臺服務器上不同的數據庫),實際上是爲了防止DTC升級使用DbConnection.ChangeDatabase()方式:

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB"; 
static string db2 = "TestDB2"; 

static void Main(string[] args) 
{ 
    using (var scope = new TransactionScope()) 
    { 
     using (var conn = new SqlConnection(connectionString)) 
     { 
      conn.Open(); 
      // EXECUTE INSERT 
     } 
     using (var conn2 = new SqlConnection(connectionString)) 
     { 
      conn2.Open(); 
      conn2.ChangeDatabase(db2); 
      // EXECUTE INSERT 
     } 
     scope.Complete(); 
    } 
} 

只要確保你永遠Open()的連接,而另一個人仍然開放。在這種情況下,你會升級。

+0

謝謝!這可能是我的交易範圍 – Martin

+0

的票證是否有這種方法的任何性能問題?所有使用changedatabase()的缺點? – Martin

+0

我沒有做任何基準,但在運行會話期間更改數據庫(儘管存在兩個'SqlConnection'對象,底層TCP會話是相同的)並不是什麼大問題,如果有的話,我會感到驚訝是任何性能問題。 –