2013-08-05 41 views
0

我不知道下面的代碼模式:處置的SqlConnection時拋出異常

static SqlConnection getcon() 
    { 
     SqlConnection con = new SqlConnection("data source=foobar.."); 
     con.Open(); 

     // is con Disposed automatically or will it leak and live 
     // forever when exception is thrown? 

     throw new Exception("exception"); 
     return con; 
    } 

    static void Main(string[] args) 
    { 
     try 
     { 
      using (var scope = new TransactionScope()) 
      using (var con = getcon()) 
      using (var cmd = new SqlCommand("UPDATE SomeTable SET Column1 = 'test'", con)) 
      {     
       cmd.ExecuteNonQuery(); 

       scope.Complete(); 
      } 
     } 
     catch  
     { 
     } 
    } 

這是使用SqlConnection一個安全的方式(獲取從getcon()方法的連接)?當拋出異常或者它會永遠存在時,函數是否會退出?

目的,爲什麼我要把這個GetCon()方法是縮短代碼和包裹連接創建開放在一條線(using (var con = getcon()) ..)

+1

我編輯了您的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

+0

好的!但是,即使在「使用」-line中出現異常時,連接也不會丟失,而不在花括號內? – Jaska

+2

爲了解決所有這些問題(並且可能導致副作用和錯誤),只需簡單地避免鍵入**代碼('conn.Open()')的一行**看起來像是一個非常錯誤且過早的優化 - 不要這樣做。這是不值得的。 –

回答

2
is con Disposed automatically or will it leak and live orever when exception is thrown? 

throw new Exception("exception"); 
return con;//your code 

其實return con;線可達。換句話說,它永遠不會在這裏執行。你不會返回con方法實際上通過拋出Exception退出。所以你的連接將不會被清除here

當方法退出(例外)局部變量超出Scope和你有相同的無管理的參考,所以很明顯你con受到Garbage Collection

will it leak and live orever when exception is thrown? 

回答是否定的,垃圾回收器將回收由Connection使用的內存的關懷和當Dispose(true)通常從Finalizer叫你的連接將被關閉。

編輯

假設你的GET CON方法不拋出任何異常,並返回一個ConnectionException拋出如下

using (var scope = new TransactionScope()) 
using (var con = getcon()) 
using (var cmd = new SqlCommand("UPDATE SomeTable SET Column1 = 'test'", con)) 
{ 
    throw new Exception("Oops");//Throw excception somewhere here    
    cmd.ExecuteNonQuery(); 
    scope.Complete(); 
} 

上面的代碼將保證清理時,因爲一個異常被拋出你在using聲明中包裝con

希望這會有所幫助

2

你寫你getcon方法的方式(我假設你做了明確來測試一些東西),con會在拋出異常的時候被釋放。自從'返回con'以來在拋出異常之後,它將永遠不會返回到調用代碼,並且只要getcon退出(用於超出範圍)就會被釋放。

1

我想jaadooviewer的答案是正確的,但它似乎可以完全避免在getcon方法中使用try/catch塊的問題。

try 
{ 
    SQLConnection con = new SQLConnection("..."); 
    con.Open(); 
    if (/*condition*/) 
     throw new Exception("Exception Condition Satisfied"); 
} 
catch (Exception ex) 
{ 
    con.Dispose(); 
    throw ex; 
} 
return con; 
+0

這裏的主要問題是使用塊將'getcon()'方法內的觸角延伸或不延伸 – Jaska

+0

@Jaska - 是的。 'getcon()'在你的使用塊中被調用,所以它在塊內「可以說」。 – Tim

+0

你可能會希望'catch(Execption)'與'throw'結合起來''所以你不會丟失堆棧跟蹤。 (也可以'Dispose()'隱式調用'Close()''SqlConnection',所以你不需要在catch塊中調用它) –