2011-10-27 56 views
5

我剛剛建議將整個using塊放在try之內,否則using範圍將防止捕捉異常。但是,如果拋出異常,是不是會阻止using正確地處理其資源?如果我有下面的代碼,我應該在哪裏放置try塊?使用IDisposable的時候放置try/catch的位置

using (connSQL = new SqlConnection(strConn)) 
{ 
    connSQL.Open(); 
    using (SqlCommand commSQL = new SqlCommand(strPreparedStatement, connSQL)) 
    { 
     if (sqlParameters != null) 
     { 
      for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++) 
      { 
       commSQL.Parameters.Add(sqlParameters[i]); 
      } 
     } 
     drSQL = commSQL.ExecuteReader(); 
     dtReturn.Load(drSQL); 

     commSQL.Parameters.Clear(); 
    } 
} 

在這個應用程序中,確保連接到數據庫由於例外而不會累積起來要重要得多。

回答

9

using聲明將已阻止連接積聚 - 它的東西清除側爲你,通過在finally塊中調用Dispose有效地作爲try/finally塊。如果你想要一個try/catch塊,你可以把它放在內部或外部 - 但你確定它不應該在一個更高的水平?你真的期待處理的例外嗎?

順便說一句,目前還不清楚爲什麼你會從結算時該命令將被反正設置在命令的參數...

我會鼓勵你的using語句內聲明的變量太多,這樣你就不會結束試圖從他們的塊之外讀:

using (SqlConnection connSQL = new SqlConnection(strConn)) { 

一般情況下,更願意給你的變量作爲一個狹窄的範圍成爲可能。哦,你的SqlDataReader也應該在using聲明中。這可能並不重要,因爲無論如何你都要關閉連接和命令,但是我會把它作爲一個原則 - 它實現了IDisposable,所以你應該處理它。

哦,你的方式迭代sqlParameters是相當長的時刻。 foreach使它更簡單,即使它不,我會使用for (int i = 0; i < sqlParameters.Length; i++),除非我有理由相信它不是一個「簡單」的數組。

所以,我的等效代碼會是這個樣子:

using (SqlConnection connection = new SqlConnection(connectionString)) 
{ 
    connection.Open(); 
    using (SqlCommand command = new SqlCommand(strPreparedStatement, connection)) 
    { 
     if (sqlParameters != null) 
     { 
      // If sqlParameter is an array, you can just use 
      // command.Parameters.AddRange(sqlParameters) instead 
      foreach (SqlParameter parameter in sqlParameters) 
      { 
       command.Parameters.Add(parameter); 
      } 
     } 
     using (SqlDataReader reader = command.ExecuteReader()) 
     { 
      DataTable table = new DataTable(); 
      // Perform any extra initialization here 
      table.Load(reader); 
      return table; 
     } 
    } 
} 
+0

有趣。所有非常好的點。我讚賞關於'SqlDataReader'的一點。我完全錯過了。 – Andrew

+0

看到你的編輯,再簡單得多。謝謝。 – Andrew

1

沒有必要把trycatch,因爲using隱含地實現它,實際上它最終使用try,並確定它會處理對象。

這是MSDN using Sample關於嘗試捕捉和使用:

{ 
    Font font1 = new Font("Arial", 10.0f); 
    try 
    { 
    byte charset = font1.GdiCharSet; 
    } 
    finally 
    { 
    if (font1 != null) 
     ((IDisposable)font1).Dispose(); 
    } 
} 

等於:

using (Font font3 = new Font("Arial", 10.0f), 
      font4 = new Font("Arial", 10.0f)) 
{ 
    // Use font3 and font4. 
} 
+0

Nitpick - ''using' implements try/finally,not try/catch – Greg

+0

錯,它不會執行catch。但只能嘗試,最後! – Zenwalker

+0

@zenwalker我寫它隱含地實現它(我的意思是OP想要從try catch中得到什麼),我也說過,最後用try來做。 –

2

你需要用數據讀取器在using語句,以及因爲它是一次性的資源:

using (var connSQL = new SqlConnection(strConn)) 
using (var commSQL = connSQL.CreateCommand()) 
{ 
    connSQL.Open(); 
    commSQL.CommandText = strPreparedStatement; 
    if (sqlParameters != null) 
    { 
     for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++) 
     { 
      commSQL.Parameters.Add(sqlParameters[i]); 
     } 
    } 
    using (var drSQL = commSQL.ExecuteReader()) 
    { 
     dtReturn.Load(drSQL); 
    } 
} 

我也已經將連接,命令和數據讀取器對象本地定義到這個塊範圍中。

try/finally聲明而言,您不再需要聲明,因爲using聲明確保即使在發生異常時也會調用Dispose方法。這種用於sql連接和命令的方法可以確保正確釋放它們。

+0

好點。我錯過了,直到這裏的答案指出了這一點。我也更喜歡使用組合的'使用'塊。我不確定爲什麼我不認爲我可以在這裏使用它。 – Andrew