2009-06-19 18 views
7

Hoy he encontrado un error en uno de nuestros proyectos: hay una conexión con la base de datos que nunca se cierra, me refiero al método Close() nunca se llama. Sin embargo, cuando cierro la aplicación, la conexión se cierra (verificada en el estudio de gestión sql muchas veces). ¿Por qué?¿Qué sucede con una conexión de base de datos no cerrada?

Respuesta

4

La conexión se cerrará cuando la aplicación salga. Lea en SqlConnection's Finalize. De la documentación de MSDN para Object.Finalize:

"Durante el cierre de un dominio de aplicación, Finalize se invoca automáticamente en objetos que no están exentos de finalización, incluso los que todavía están accesibles."

+0

"Si el SqlConnection queda fuera del alcance, no se cerrará. Por lo tanto, debe cerrar la conexión de forma explícita llamando a Close o Dispose". -esto es también de msdn, ¿no significa que la conexión puede no cerrarse si no llamas a Close()? – agnieszka

+0

Básicamente puedes hacer Close, Dispose o usar() {}, como deberías hacer de todos modos. Cuando la aplicación se cierre, las conexiones también se cerrarán, por la razón que he indicado en mi respuesta. – RichardOD

+0

Además, si en algún momento el GC decide finalizar las conexiones, también se cerrarán. – RichardOD

1

Las conexiones SQL son costosas de crear y ADO.NET utiliza una técnica llamada agrupación de conexiones que permite reutilizarlas.

Presupuesto de MSDN:

Se recomienda encarecidamente que siempre cierra la conexión cuando termine de usarlo, de modo que se ser devuelto a la agrupación de conexiones y ser reutilizado.

Si el tamaño máximo de la agrupación ha sido alcanzado y no hay conexión utilizable es disponible, la solicitud está en cola. El agrupador intenta reclamar las conexiones hasta que se alcanza el tiempo de espera (el valor predeterminado es 15 segundos). Si la agrupación no puede satisfacer la solicitud antes de los tiempos de conexión , se produce una excepción.

+1

De hecho, debido a la agrupación de conexiones, una conexión de SQL nunca se cierra realmente; simplemente se devuelve al grupo para volver a utilizarse cuando se llama a Cerrar. Estará cerca cuando se destruya el dominio de la aplicación que es cuando salga de la aplicación. Por lo tanto, si nunca llama a Cerrar, la conexión no se reutilizará y, una vez agotado, obtendrá una excepción. –

+0

@ darin- nunca cerrado es incorrecto. Después de una cierta cantidad de inactividad, la conexión se cerrará, pero eso es solo una trampa. – RichardOD

+1

@RichardOD, no diría que es quisquilloso. De hecho, no sabía este hecho. Muchas gracias por esta precisión. –

1

Cuando salga de la aplicación de manera normal, espero que se ejecuten los finalizadores. Cerrarán la conexión si aún está abierta. Simplemente no dependa de esto: puede pasar un tiempo antes de que esos finalizadores se ejecuten en el funcionamiento normal de su aplicación, por lo que mantendrá demasiadas conexiones abiertas.

Cuando la aplicación falla, quizás el finalizador no se ejecute, dejando la conexión abierta más allá de la duración de la aplicación.

2

Otra cosa a tener en cuenta aquí es que en .Net, puede envolver sus conexiones en un bloque de uso, y eso cerrará y eliminará sus conexiones por usted. Por lo que la falta de una explícita Cerrar() no es una mala cosa si usted tiene sus utilizando bloques de allí ...

// this using block will auto close & dispose your connection... 
using (var conn = new SqlConnection(...)) 
{ 
    conn.Open(); 
    // database code here with no explicit close 

} 

que es el equivalente funcional de un try/finally con un conn.Close en el finalmente. Muchos desarrolladores pasan por alto los bloques de uso; asegúrese de que no esté haciendo lo mismo en este caso.

Si reescribes el código para cerrar tus conexiones, es una buena práctica usar el uso de bloques alrededor de todos tus objetos de base de datos (conexión, comando, lector) para asegurarte de que están cerrando y eliminando cuando caigan fuera del alcance del bloque de uso. Definitivamente, sugeriría escribirlos en tu código en lugar de solo conn.Close() donde sea necesario.

+0

Yeap esa es la forma en que lo hago. Si usa FXCop, nunca tendrá problemas, ya que le advierte que no debe llamar a Dispose. – RichardOD

+0

No hubo uso de bloque, sé sobre ellos. – agnieszka

+0

y no es la respuesta a la pregunta – agnieszka

Cuestiones relacionadas