Quiero aclarar esta situación.
De acuerdo con las pautas de Microsoft, es una buena práctica proporcionar un Close
método cuando sea adecuado. Aquí hay una cita de las pautas de diseño de Framework
Considere proporcionar un método Close()
, además del Dispose()
, si cerca es terminología estándar en el área. Al hacerlo, es importante que haga que la Close
implementación sea idéntica a Dispose
...
En la mayoría de casos Close
y Dispose
métodos son equivalentes. La principal diferencia entre Close
y Dispose
en el caso de SqlConnectionObject
es:
Una aplicación puede llamar Close
más de una vez. No se genera ninguna excepción.
Si llamó al Dispose
método, el
SqlConnection
estado del objeto se restablecerá. Si intenta llamar a cualquier método en un SqlConnection
objeto desechado , recibirá una excepción.
Eso dijo:
- Si usa el objeto de conexión una vez, use
Dispose
.
- Si el objeto de conexión debe reutilizarse, utilice el
Close
método
con.Open() con.Close();
2con.Open(); // reuse
3.con.Dispose(); // use one time con.Open(); // error
Como de costumbre, la respuesta es: depende. Las diferentes clases se implementan
IDisposable
de diferentes maneras, y depende de usted hacer la investigación necesaria.Hasta donde
SqlClient
llega, la práctica recomendada es hacer lo siguiente:¡ Deberías estar llamando
Dispose
(oClose
*) en la conexión! No , no esperar a que el recolector de basura para limpiar su conexión, esto va a atar a las conexiones en la piscina hasta el siguiente ciclo de GC (por lo menos). Si llamaDispose
, no es necesario llamarClose
, y dado que lausing
construcción hace que sea tan fácil de manejarDispose
correctamente, realmente no hay razón para llamarClose
.Las conexiones se agrupan automáticamente y llamar
Dispose
/Close
en la conexión no cierra físicamente la conexión (en circunstancias normales). No intente implementar su propia agrupación.SqlClient
realiza una limpieza en la conexión cuando se recupera del grupo (como restaurar el contexto de la base de datos y las opciones de conexión).* si está llamando
Close
, asegúrese de hacerlo de manera segura (es decir, en una captura o finalmente bloquear).fuente
conn.Close(); // Optional
no es opcional. Es redundante e innecesario. Desecha el objeto dos veces y algunas herramientas de análisis de código lo marcarán como advertencia.using (var x = ..) { x.Dispose(); }
, en cuyo casox
realmente está "dispuesto dos veces".¡Necesitas llamar a Dispose ()!
Dispose () es para que el desarrollador llame, el recolector de basura llama a Finalize (). Si no llama a Dispose () en sus objetos, los recursos no administrados que usaron no se eliminarán hasta que el recolector de basura se acerque y las llamadas finalicen (y quién sabe cuándo sucederá eso).
Este escenario se llama Finalización no determinista y es una trampa común para los desarrolladores de .net. Si está trabajando con objetos que implementan IDisposable, ¡llame a Dispose () en ellos!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
Si bien puede haber muchas instancias (como en SqlConnection) donde llama a Disponse () en algún objeto y simplemente llama a Cerrar () en su conexión o cierra un identificador de archivo, ¡ casi siempre es su mejor opción llamar a Dispose ()! a menos que planee reutilizar el objeto en un futuro muy cercano.
fuente
Dispose
.Dispose()
si no está utilizandousing()
una clase que implementaIDisposable
. Si la clase que se llama implementa IDisposable y ha incluido su uso en la páginausing()
, puede deshacerse de élDispose()
(juego de palabras, así que dispare). El usoClose()
, sin embargo, se recomienda con cualquier cosa que utiliza de forma explícitaOpen()
, que yo sepa.Close
una conexión, Postgres establece automáticamente el identificador de conexión ennull
. A partir de ahí, no se puedeDispose
un identificador de conexión SQL que ya esté configurado ennull
.Porque
SqlConnection
, desde la perspectiva de la conexión misma, son equivalentes. Según Reflector, lasDispose()
llamadasClose()
además de realizar algunas operaciones adicionales de liberación de memoria, principalmente al establecer miembros iguales a nulos.Para Stream, en realidad son equivalentes.
Stream.Dispose()
simplemente llama a Close ().fuente
Component
lo que no parece hacer nada para intentar llamarClose()
. No puedo ver en ninguna parteDBConnection
niSqlConnection
eso se relaciona con ninguna de esas notificaciones. Sin embargo, tiene un privado alDisposeMe()
que no se hace referencia en ninguna parte .Este posible consejo rápido se convirtió en una respuesta larga. Lo siento.
Como señaló Tyler en su buena respuesta, llamar
Dispose()
es una gran práctica de programación. Esto se debe a que se supone que este método "reúne" toda la liberación de recursos necesaria para que no haya recursos abiertos innecesarios. Si escribió un texto en un archivo, por ejemplo, y no pudo cerrar el archivo (libere el recurso), permanecerá abierto y nadie más podrá escribir en él hasta que aparezca el GC y haga lo que debe hacer. hecho.Ahora, en algunos casos habrá métodos de "finalización" más específicos para la clase con la que está tratando, como
StreamWriter.Close()
, que anulaTextWriter.Close()
. De hecho, por lo general son más adecuados para la situación: un StreamWriterClose()
, por ejemplo, descarga el flujo y el codificador subyacente antesDispose()
del objeto. ¡Frio!Sin embargo, al navegar por MSDN encontrará que incluso Microsoft a veces se confunde por la multitud de cerradores y trituradores. En esta página web , por ejemplo, en algunos ejemplos
Close()
se llama antes de lo implícitoDispose()
(vea el uso de la declaración si no entiende por qué es implícito), y en uno en particular no se molestan. ¿Por qué sería eso? Yo también estaba perplejo.La razón por la que pensé (y, enfatizo, esta es una investigación original y seguramente podría perder reputación si me equivoco) es que
Close()
podría fallar, produciendo una excepción al dejar recursos abiertos, mientrasDispose()
que seguramente los liberaría . Es por ello que unaDispose()
siempre debe salvaguardar unaClose()
llamada (perdón por el juego de palabras).Y sí, supongo que Microsoft resbaló en ese ejemplo. Quizás esa marca de tiempo nunca se volcaría en el archivo.
Estoy arreglando mi viejo código mañana.
Editar: lo siento Brannon, no puedo comentar tu respuesta, pero ¿estás seguro de que es una buena idea llamar
Close()
a unfinally
bloque? Supongo que una excepción de eso podría arruinar el resto del bloque, que probablemente contendría un código de limpieza importante.Responda a Brannon: genial, simplemente no olvide llamar
Close()
cuando sea realmente necesario (por ejemplo, cuando se trata de transmisiones, no sé mucho sobre conexiones SQL en .NET).fuente
Typecast a iDisposable, y llame a dispose en eso. Eso invocará cualquier método configurado como implementación "iDisposable.Dispose", independientemente de cómo se llame la función.
fuente
IDisposable.Dispose
, pero eso no significa que ese sea el nombre. Tenga en cuenta que en vb.net, es posible tener una función vinculada a múltiples miembros de la interfaz con nombres que no necesitan estar relacionados con el de la función.using (myObj as IDisposable)
En general, enfrentamos problemas en Cerrar (), Abortar () y Eliminar (), pero déjame decirte la diferencia entre ellos.
1) ABORTAR: - No sugeriré usar esto porque cuando se llama a abortar, el cliente eliminará la conexión sin decirle al servidor, por lo que el servidor esperará una cierta cantidad de tiempo (aproximadamente 1 minuto). Si tiene una solicitud masiva, no puede usar abort () porque puede causar un tiempo de espera para su grupo de conexiones limitado.
2) Cerrar: - Cerrar es una muy buena manera de cerrar la conexión porque al cerrar la conexión llamará al servidor y confirmará que el servidor también se cerrará por ese lado.
Aquí, una cosa más para mirar. En algunos casos, si se genera un error, entonces no es una buena forma de escribir código finalmente en esa conexión.close () porque en ese momento se producirá un error en el estado de comunicación.
3) Desechar: - Es un tipo de cierre, pero después de cerrar la conexión no puede volver a abrirla.
Así que intenta de esta manera,
fuente
client != null
es incorrecta / engañosa porque no protege todos los usos. Además, no estoy seguro de cómo el código puede llegar al estado de "esta conexión no está abierta y debería cerrarse".