¿Qué tan malo es no desechar () SqlConnections?

14

Personalmente, exploto en colmenas si no pongo objetos ADO que implementan IDisposable en el uso de declaraciones. Pero en mi contrato actual, descubrí que su código de "proveedor de acceso a datos" de marco empresarial local no 1) implementa IDisposable y 2) llama a Dispose () en cualquier cosa que use, en cualquier momento, nunca. Los usuarios se han quejado mucho de los problemas de rendimiento en las aplicaciones Winforms que utilizan mucho este marco para el acceso a datos, y aunque hay MUCHOS otros problemas en el código que podrían estar afectando el rendimiento, este simplemente me grita y es más Frutos bajos que los demás.

Entonces, más allá de decir algo como "Desechar está ahí por una razón, úselo", ¿qué puedo decirles a estas personas para convencerlos de que esto es realmente malo?

AJ Johnson
fuente
55
Je ... supongo que, en algún momento, no será necesario convencer :)
Dr. Hannibal Lecter

Respuestas:

6

Diría que lo mejor que puede hacer es señalarlos a los Patrones y Prácticas de Microsoft Dispose() aquí . Permítales ver todas las consecuencias de no utilizar esta herramienta que está justo en frente de ellos.

Jesse C. Slicer
fuente
1
Solo desearía poder encontrar una versión que no gritara "este es contenido retirado" en la parte superior.
AJ Johnson el
Sabes, mis ojos simplemente pasaron por alto eso. Pero ahora, leyéndolo detenidamente, me pregunto qué tecnologías podrían "seguir utilizando" las personas que están retiradas de esa página. Tal vez CAS?
Jesse C. Slicer
Al escanearlo más de cerca, la mayor parte de esto todavía me parece relevante. Tampoco estoy seguro de por qué está marcado como retirado.
AJ Johnson el
10

Si no llama al método Dispose en una conexión SQL, cuando termine de usarlo, esa conexión NO volverá al grupo de conexiones.

Si tiene problemas de rendimiento, supongo que las conexiones máximas se abren en su base de datos. Un DBA podría confirmar esto fácilmente.

Las mejores prácticas de Microsoft requieren que coloque su código de conexión dentro de una instrucción de uso, asegurándose de que la conexión se elimine y que la conexión se devuelva al grupo.

Walter
fuente
Llamar Closees suficiente para liberar de nuevo al grupo de conexiones. La pregunta no establece que Closeno se usa explícitamente .
usuario2864740
9

El grupo de conexiones de la base de datos tiene un tamaño limitado y, si se llena, las nuevas conexiones esperarán a que se liberen las antiguas. Si no los desecha tan pronto como termine con ellos, eventualmente se liberarán cuando se ejecute el finalizador, pero eso es una cantidad de tiempo indeterminada en el futuro ... Entonces, en el mejor de los casos, va a ver largas demoras al abrir nuevas conexiones.

En el peor de los casos, podrían haber deshabilitado el grupo de conexiones. Tal vez descubrieron que después de un tiempo su aplicación devolvía errores de "tiempo de espera esperando conexión" y deshabilitar el grupo de conexiones "resolvió" ese problema. Sin embargo, esto es mucho peor porque significa que está creando una conexión completamente nueva cada vez, lo que sorprendentemente requiere muchos recursos. Si tiene cientos de conexiones abiertas a la base de datos, no es de extrañar que esté teniendo problemas de rendimiento.

La forma correcta de resolver todos estos problemas es deshacerse de su conexión tan pronto como haya terminado. La mejor idea es mantener la conexión abierta durante exactamente el tiempo que sea necesario y no más.

Dean Harding
fuente
1
Es un poco peor que esto, incluso. Si se realiza una copia de seguridad suficiente del grupo, muchos intentos de conexión eventualmente fallarán, incluidos los intentos de conexión de las herramientas de administración, y usted puede bloquear efectivamente nuestra base de datos.
Joel Coehoorn
3

En cualquier aplicación seria, diría que es bastante malo. No solo dejará estos objetos flotando alrededor del rendimiento de eliminación, sino que también es simplemente poco profesional. La buena noticia es que Microsoft implementa Finalizar en la jerarquía de objetos.

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

Toma System.Data.SqlClient.SqlConnectionpor ejemplo:

System.ComponentModel.Component <: implementa el patrón de disposición Finalizar.
    El |
System.Data.Common.DbConnection
    El |
System.Data.SqlClient.SqlConnection

Los objetos eventualmente serán eliminados, pero la naturaleza no determinista causa estragos en el rendimiento.

ChaosPandion
fuente
0

Bueno, por un lado, no estás terminando la conexión. Por lo tanto, debe: a) Descartarse automáticamente o b) Obtener un ciclo y actualizarse aunque el cliente no lo use.

Supongo que b) debido al golpe de rendimiento que estás describiendo. Sin embargo, es probable que esa no sea la única razón.

DEBE cerrar sus conexiones, preferiblemente en el lado del cliente, pero también debe implementar una prueba de fallas en el lado del servidor. De lo contrario, solo tiene una basura adicional acumulada que su servidor de base de datos debe procesar hasta que se publique en God-know-when.


fuente