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

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

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


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

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


3

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


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í)


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.