2009-07-28 32 views
100

Por mi otro question here about Disposable objects, ¿debemos llamar a Close() antes del final de un bloque de uso?¿Debo cerrar() un SQLConnection antes de que se elimine?

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

Respuesta

96

Puesto que usted tiene un bloque usando, se llamará al método Dispose de la SQLCommand y se 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

¿_this._poolGroup = null; _ significa que la conexión no está volviendo al grupo de conexiones? entonces tendré n-1 conexiones? –

1

No, la clase SqlConnection hereda de IDisposable, y cuando se encontró con el fin de utilizar (para el objeto de conexión), se llama automáticamente al botar en la clase SqlConnection.

3

No, tener el bloque de Uso llama al Dispose() para usted de todos modos, por lo que no es necesario llamar al Close().

+0

Lo siento, debería haber dicho que para la mayoría de los objetos que implementan IDisposable y tienen un método Close(), llamando extremos close() llamando a Dispose() detrás de las escenas para usted de todos modos. –

+6

¿No es al revés - 'Dispose()' llama 'Close()', no viceversa? – Town

+1

Son ambos, por lo general. Por alguna razón, decidieron implementar que Close llamara también a Dispose.Para una Conexión Sql esto no es un gran problema, pero StreamWriters arrojará una excepción si cierras y luego los Descartas. Creo 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. (ManualResetEvent y arroyos creo que se comportan como esto)

20

Desmontaje de SqlConnection 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); 
} 

se llama a Close() dentro de Dispose()

+1

@statenjason: ¿podría decir que cómo se aprovecha el uso de desensambladores línea .net reflector? – odiseh

+3

@odiseh acaba de descargar .NET Reflector, ejecute reflector.exe y puede abrir cualquier DLL .NET (incluida la biblioteca estándar). Le proporciona una estructura de árbol similar al buscador de objetos de Visual Studio, sin embargo, puede hacer clic derecho en cualquier clase o método y hacer clic en "desmontar", le devolverá la fuente en C# o VB, lo que haya seleccionado en el opciones. – statenjason

3

Usando Reflector, se puede ver que º El método e Dispose de SqlConnection realmente llama al Close();

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

El uso de la palabra clave cerrará la conexión correctamente, por lo que no es necesario realizar una llamada adicional a Cerrar.

Del artículo de MSDN en SQL Server Connection Pooling:

"Recomendamos fuertemente que siempre cierra la conexión cuando se está terminado de usarlo de manera que se le devolverá la conexión a la piscina Puede. hacer esto utilizando las Cerrar o disponer métodos del objeto de conexión o al abrir todas las conexiones dentro de una instrucción using en C#"

La implementación real de SqlConnection.Dispose usando .NET Reflector es el 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 el reflector \ ILspy como el siguiente tipo, pero los documentos son los que me gustaría encontrar para encontrar mis respuestas. – mlhDev

Cuestiones relacionadas