¿en un bloque "using" se cierra una conexión SqlConnection en retorno o excepción?
Primera pregunta:
Digamos que tengo
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
¿Se cierra la conexión? Porque técnicamente nunca llegamos a la última }
como return
antes de ella.
Segunda pregunta:
Esta vez tengo:
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
}
catch (Exception) { /*Handle error*/ }
Ahora, digamos que en algún lugar del try
obtenemos un error y queda atrapado. ¿La conexión todavía se cierra? Porque de nuevo, saltamos el resto del código en el try
y vamos directamente a la instrucción catch
.
Estoy pensando ¿demasiado linealmente en cómo funciona using
? es decir, ¿Dispose()
simplemente se llama cuando dejamos el ámbito using
?
7 answers
- Sí
- Sí.
De cualquier manera, cuando el bloque using sale (ya sea por finalización exitosa o por error) se cierra.
Aunque creo que sería mejor organizar así porque es mucho más fácil ver lo que va a pasar, incluso para el nuevo programador de mantenimiento que lo soportará más adelante:
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
try
{
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
catch (Exception)
{
/*Handle error*/
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-20 21:30:32
Sí a ambas preguntas. La instrucción using se compila en un bloque try/finally
using (SqlConnection connection = new SqlConnection(connectionString))
{
}
Es lo mismo que
SqlConnection connection = null;
try
{
connection = new SqlConnection(connectionString);
}
finally
{
if(connection != null)
((IDisposable)connection).Dispose();
}
Editar: Fijar la escayola a Desechable http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-18 15:52:16
Aquí está mi Plantilla. Todo lo que necesita para seleccionar datos de un servidor SQL. La conexión se cierra y se elimina y se detectan errores en la conexión y la ejecución.
string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString;
string selectStatement = @"
SELECT TOP 1 Person
FROM CorporateOffice
WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%'
ORDER BY IntelligenceQuotient DESC
";
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand comm = new SqlCommand(selectStatement, conn))
{
try
{
conn.Open();
using (SqlDataReader dr = comm.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
Console.WriteLine(dr["Person"].ToString());
}
}
else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
}
}
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
if (conn.State == System.Data.ConnectionState.Open) conn.Close();
}
}
* Revisadas: 2015-11-09 *
Como sugiere NickG; Si demasiados frenos te molestan, formatea así...
using (SqlConnection conn = new SqlConnection(connString))
using (SqlCommand comm = new SqlCommand(selectStatement, conn))
{
try
{
conn.Open();
using (SqlDataReader dr = comm.ExecuteReader())
if (dr.HasRows)
while (dr.Read()) Console.WriteLine(dr["Person"].ToString());
else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
}
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
if (conn.State == System.Data.ConnectionState.Open) conn.Close();
}
Por otra parte, si trabajas para EA o DayBreak games, también puedes renunciar a cualquier salto de línea porque son solo para las personas que tienen que volver y mirar tu código más tarde, ¿y a quién le importa? ¿Tengo razón? Quiero decir 1 línea en lugar de 23 significa que soy un mejor programador, ¿verdad?
using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); }
Uf... OK. Lo saqué de mi sistema y he terminado de divertirme por un tiempo. Continúa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-21 20:37:28
Dispose simplemente se llama al salir del ámbito de uso. La intención de" usar " es dar a los desarrolladores una forma garantizada de asegurarse de que los recursos se eliminen.
De MSDN :
Una sentencia using puede salir cuando se alcanza el final de la sentencia using o si se lanza una excepción y control abandona el bloque de sentencia antes del final de la sentencia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-17 21:02:07
Using
genera un try / finally alrededor del objeto que se está asignando y llama Dispose()
para usted.
Te ahorra la molestia de crear manualmente el bloque try / finally y llamar a Dispose()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-17 21:03:09
En su primer ejemplo, el compilador de C # traducirá la instrucción using a lo siguiente:
SqlConnection connection = new SqlConnection(connectionString));
try
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
finally
{
connection.Dispose();
}
Finalmente declaraciones siempre llama antes de que una función devuelve y así, la conexión será siempre cerrado/eliminados.
Por lo tanto, en su segundo ejemplo, el código se compilará de la siguiente manera:
try
{
try
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
finally
{
connection.Dispose();
}
}
catch (Exception)
{
}
La excepción quedará atrapada en la sentencia finally y la conexión se cerrará. La excepción no se verá en la cláusula de captura exterior.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-17 21:14:58
Escribí dos usando instrucciones dentro de un probar / atrapar block y pude ver que la excepción estaba siendo atrapada de la misma manera si se coloca dentro de la interior usando sentencia al igual que ShaneLS ejemplo.
try
{
using (var con = new SqlConnection(@"Data Source=..."))
{
var cad = "INSERT INTO table VALUES (@r1,@r2,@r3)";
using (var insertCommand = new SqlCommand(cad, con))
{
insertCommand.Parameters.AddWithValue("@r1", atxt);
insertCommand.Parameters.AddWithValue("@r2", btxt);
insertCommand.Parameters.AddWithValue("@r3", ctxt);
con.Open();
insertCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "UsingTest", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
No importa dónde está el probar / atrapar colocado, la excepción será capturada sin problemas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:30