2009-11-27 10 views
22

que suelen utilizar código como este:¿Se requiere SqlCommand.Dispose() si se eliminará SqlConnection asociado?

using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString)) 
{ 
    var command = connection.CreateCommand(); 
    command.CommandText = "..."; 
    connection.Open(); 
    command.ExecuteNonQuery(); 
} 

¿Mi command dispuesto de forma automática? O no, y tengo que envolverlo en el bloque using? ¿Es necesario disponer de SqlCommand?

+0

Es una pena que Microsoft haya hecho de SqlCommand un Componente. Si realmente necesitaran un Componente para soporte de diseñador, podría haber sido un envoltorio sobre un SqlCommand liviano que no implementa IDisposable. –

Respuesta

22

a hacer esto:

using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString)) 
using(var command = connection.CreateCommand()) 
{ 
    command.CommandText = "..."; 
    connection.Open(); 
    command.ExecuteNonQuery(); 
} 

no llamar a disponer en el comando no hará nada demasiado malo. Sin embargo, llamar a Dispose on se llamará supress the call to the finalizer, haciendo que las llamadas eliminen una mejora en el rendimiento.

+11

"No hacer una llamada en el comando no hará nada malo". Es cierto, pero no te acostumbres; solo es cierto para 'SqlCommand's. Por otro lado, si no elimina un 'SqlCeCommand', por ejemplo *, * su dispositivo móvil se quedará sin memoria bastante rápido. (Solo he estado allí, hecho eso ...) – Heinzi

+2

'Dispose' no suprime la finalización ya que el constructor hace eso. –

8

La política más segura es llamar siempre al Dispose() en un objeto si implementa IDisposable, ya sea explícitamente o mediante un bloque de uso. Puede haber casos en que no sea necesario, pero llamarlo de todos modos nunca debe causar problemas (si la clase está escrita correctamente). Además, nunca se sabe cuándo puede cambiar una implementación, lo que significa que cuando la llamada no era necesaria anteriormente, ahora es definitivamente necesario.

En el ejemplo que ha dado, puede agregar un bloque de uso interno adicional para el comando, así como también mantener el bloque de uso externo para la conexión.

+2

Sí, la política más segura es disponer siempre los objetos desechables, ¡especialmente si * lo * creó! No es una buena idea, por ejemplo, escribir un método que acepte una transmisión y disponer la transmisión dentro de ese método. Otra advertencia es que no siempre puede deshacerse de la declaración de uso con impunidad. Los proxies de WCF son el único ejemplo práctico que conozco. Si algo sale mal en el extremo remoto y recibe una excepción, el canal se cierra y, luego, Desechar arroja una nueva excepción, reemplazando la excepción original, que puede ser un problema grave. –

+1

¡otra razón para no usar WCF! gracias por el consejo ;-) –

1

Puede encontrar este tipo de cosas usando Reflector.

Tuve una pequeña excavación (sugiero que también excave para estar completamente seguro del resto de esto, ya que no lo intenté tan duro) y parece que cuando matas una conexión no hay eliminación de cualquier niño asociado con esa conexión. Además, en realidad no parece que la eliminación de un comando en realidad hace tanto. Establecerá un campo en nulo, se separará de un contenedor (esto puede evitar una fuga de memoria administrada) y generará un evento (esto podría ser importante, pero no puedo ver quién está escuchando este evento).

De cualquier forma, es una buena práctica usar este material en un bloque de uso o asegurarse de desecharlo utilizando un patrón de eliminación en el objeto que contiene la conexión (si tiene la intención de mantener el comando por un tiempo).

4

Sí, deberías, incluso si la implementación actualmente no está haciendo mucho, no sabes cómo se va a cambiar en el futuro (por ejemplo, las versiones de framework más recientes). En general, debe deshacerse de todos los objetos que implementen IDisposable para estar en el lado seguro.

Sin embargo, si se aplaza la operación y que no controlan el alcance completo (por ejemplo, cuando se trabaja asynchroneously, o al volver de un SqlDataReader o algo así), se puede establecer el CommandBehavior a CloseConnection modo que tan pronto como el lector está hecho, la conexión está cerrada/dispuesta adecuadamente para usted.

2

En la práctica, puede omitir Dispose. No libera ningún recurso. Ni siquiera suprime la finalización ya que el constructor hace eso.

En teoría, Microsoft podría cambiar la implementación para tomar un recurso no administrado, pero espero que salgan con una API que elimine la clase base Component mucho antes de que lo hicieran.

Cuestiones relacionadas