2011-10-27 8 views
5

Me acaban de aconsejar poner un bloque completo using dentro de un try, de lo contrario, el alcance using evitará que la excepción sea atrapada. Sin embargo, ¿no impediría que el using elimine correctamente sus recursos si se lanzara una excepción? Si tengo el siguiente código, ¿dónde debo colocar los bloques try?Dónde ponerlo try/catch cuando use IDisposable

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(); 
    } 
} 

En esta aplicación, es mucho más importante asegurarse de que las conexiones a la base de datos no comiencen a acumularse debido a excepciones.

Respuesta

9

La declaración using ya estará impedir conexiones se acumule - lo hace la parte de limpieza de las cosas para usted , al ser efectivamente un bloque try/finally con una llamada al Dispose en el bloque finally. Si también quiere un bloque try/catch, puede colocarlo adentro o afuera, pero ¿está seguro de que no debería estar en un nivel superior? ¿Cómo se espera manejar la excepción?

Dicho sea de paso, no está claro por qué se está despejando los parámetros de la orden cuando el comando está a punto de ser eliminado de todos modos ...

les animo a declarar las variables dentro de las declaraciones demasiado using , para que no terminen tratando de leer de ellos fuera del bloque:

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

En general, prefieren dar a sus variables como un alcance más estrecho posible. Ah, y su SqlDataReader también debería estar en una declaración using. Puede que no importe ya que está cerrando la conexión y el comando de todos modos, pero lo haría como un punto de principio: implementa IDisposable, por lo que debe deshacerse de él.

Ah, y su forma de iterar sobre sqlParameters es bastante larga en este momento. foreach lo hace más simple, y aunque no fuera así, usaría for (int i = 0; i < sqlParameters.Length; i++) a menos que tuviera motivos para creer que no era una matriz "simple".

lo tanto, mi código equivalente sería algo como esto:

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

Interesante. Todos muy buenos puntos. Aprecio el punto acerca de 'SqlDataReader'. Eché de menos eso. – Andrew

+0

Al ver su edición, de nuevo mucho más simple. Gracias. – Andrew

1

No hay necesidad de poner trycatch porque using lo implementa implícitamente, de hecho utiliza try finally y seguro que va a disponer de los objetos.

Esta es MSDN using Sample sobre intento de captura y el uso de:

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

es igual a:

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

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

+0

Incorrecto, no implementará captura. ¡Pero solo intenta y finalmente! – Zenwalker

+0

@zenwalker Lo escribí para implementarlo implícitamente (me refiero a lo que el OP quiere de try catch) también dije que usar hacerlo con try finalmente. –

2

Es necesario para envolver el lector de datos en una instrucción using así, ya que es un recurso desechable:

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); 
    } 
} 

I también han definido los objetos de conexión, comando y lector de datos localmente definidos en este ámbito de bloque.

En lo que respecta a una declaración try/finally, ya no la necesita, ya que las declaraciones using aseguran que se invocará el método Dispose incluso en el caso de excepciones. Y este método para conexiones y comandos sql asegura que los libere adecuadamente.

+0

Buen punto. Me había perdido eso hasta que las respuestas aquí lo señalaran. También prefiero usar los bloques combinados 'using'. No estoy seguro de por qué no pensé que podría usar eso aquí. – Andrew

Cuestiones relacionadas