¿Tengo que Cerrar () una SQLConnection antes de que se elimine?

113

Según mi otra pregunta aquí sobre los objetos desechables , ¿deberíamos llamar a Close () antes del final de un bloque de uso?

using (SqlConnection connection = new SqlConnection())
using (SqlCommand command = new SqlCommand())
{
    command.CommandText = "INSERT INTO YourMom (Amount) VALUES (1)";
    command.CommandType = System.Data.CommandType.Text;

    connection.Open();
    command.ExecuteNonQuery();

    // Is this call necessary?
    connection.Close();
}
John Bubriski
fuente

Respuestas:

107

Como tiene un bloque using, se llamará al método Dispose del SQLCommand y cerrará la conexión:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
CMS
fuente
1
¿Hace this._poolGroup = null; significa que la conexión no regresa al grupo de conexiones? ¿Entonces tendré n-1 conexiones?
Royi Namir
25

Desmontaje de SqlConnection desde el uso de .NET Reflector :

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }

    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Llama a Close () dentro de Dispose ()

statenjason
fuente
1
@statenjason: ¿podría decirnos cómo se aprovecha el uso del reflector .net de línea de desmontadores?
odiseh
3
@odiseh simplemente descargue .NET Reflector, ejecute reflector.exe y podrá abrir cualquier DLL .net (incluida la biblioteca estándar). Le proporciona una estructura de árbol similar al navegador de objetos de Visual Studio, sin embargo, puede hacer clic con el botón derecho en cualquier clase o método y hacer clic en "desensamblar" y luego le devolverá la fuente en C # o VB, lo que haya seleccionado en el opciones.
statenjason
20

La palabra clave using cerrará la conexión correctamente, por lo que no se requiere la llamada adicional a Cerrar.

Del artículo de MSDN sobre agrupación de conexiones de SQL Server :

"Recomendamos encarecidamente que siempre cierre la conexión cuando termine de usarla para que la conexión se devuelva al grupo. Puede hacerlo utilizando los métodos Cerrar o Dispose del objeto Conexión, o abriendo todas las conexiones dentro de un usando la declaración en C # "

La implementación real de SqlConnection.Dispose usando .NET Reflector es la siguiente:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Thomas Bratt
fuente
1
+1 para el enlace de MSDN: me gusta reflector \ ILspy como cualquier otro, pero los documentos son donde me gustaría ir para encontrar mis respuestas.
mlhDev
5

Usando Reflector , puede ver que el Disposemétodo de SqlConnectionrealmente llama Close();

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Aaron Daniels
fuente
3

No, tener el bloque Using te llama Dispose()de todos modos, por lo que no es necesario que llames Close().

Jason Evans
fuente
Lo siento, debería haber dicho que para la mayoría de los objetos que implementan IDisposable y tienen un método Close (), llamar a Close () termina llamando a Dispose () detrás de escena para usted de todos modos.
Jason Evans
6
¿No es al revés: Dispose()llamadas Close(), no viceversa?
Ciudad
1
Suelen ser ambos. Por alguna razón, decidieron implementar que Close también llamaría Dispose. Para una SqlConnection, esto no es un gran problema, pero StreamWriters lanzará una excepción si cierra y luego los elimina. Supongo que no cambiarán ese comportamiento simplemente porque es lo que la gente espera ahora.
2

No, no es necesario cerrar una conexión antes de llamar a Dispose.

Algunos objetos (como SQLConnections) se pueden reutilizar después de llamar a Close, pero no después de llamar a Dispose. Para otros objetos, llamar a Close es lo mismo que llamar a Dispose. (Creo que ManualResetEvent y Streams se comportan así)

pipTheGeek
fuente
1

No, la clase SqlConnection hereda de IDisposable, y cuando se encuentra el final del uso (para el objeto de conexión), llama automáticamente a Dispose en la clase SqlConnection.

blparker
fuente