2009-06-29 19 views
8

Tenemos un código de cliente que está utilizando la clase SqlConnection en .NET para hablar con una base de datos SQLServer. Es intermitente está fallando con este error:.NET Clase SqlConnection, agrupación de conexiones y lógica de reconexión

"ExecuteReader requiere una conexión abierta y disponible estado actual de la conexión se cierra."

La solución "temporal" es reiniciar el proceso, después de lo cual todo funciona - sin embargo, eso es obviamente insatisfactorio.

El código mantiene un caché de instancias de SqlConnection, una para cada base de datos.

Nos gustaría volver a escribir el código, pero antes de hacerlo, necesito saber algunas cosas:

Mi primera pregunta es: ¿Es ineficiente para conectar y desconectar repetidamente objetos SqlConnection, o hace la biblioteca subyacente realiza la agrupación de conexiones en nuestro nombre?

// Is this bad/inefficient? 
for(many-times) 
{ 
    using(SQLConnection conn = new SQLConnection(connectionString)) 
    { 
     // do stuff with conn 
    } 
} 

Debido a que nuestro código hace no hacer lo anterior, lo que parece ser la causa más probable del problema es que algo le sucede a la base de datos SQL Server subyacente durante el "tiempo de vida" de la conexión que hace que la conexión a cerrarse ...

Si resulta que vale la pena "almacenar en caché" objetos SqlConnection, ¿cuál es la forma recomendada de manejar todos los errores que podrían resolverse simplemente "reconectando" a la base de datos. Estoy hablando de escenarios tales como:

  • La base de datos se desconecta y se vuelve a conectar, pero el proceso de cliente no tenía transacciones abiertas mientras esto ocurría
  • La base de datos fue "desconectado", luego "reconecté "

Me di cuenta de que hay una propiedad de" Estado "en SqlConnection ... ¿hay una forma adecuada de consultar eso?

Por último, tengo una instancia de SQL Server configuración de prueba con los derechos de acceso: ¿cómo puedo ir sobre reproducir el error exacto "ExecuteReader requiere una conexión abierta y disponible estado actual de la conexión se cierra"

Respuesta

19

No, no es ineficiente crear muchos objetos SqlConnection y cerrar cada uno de ellos cuando haya terminado. Eso es exactamente lo que hay que hacer. Permita que la agrupación de conexiones de .NET Framework haga su trabajo; no intente hacerlo usted mismo. No necesita hacer nada específico para habilitar la agrupación de conexiones (aunque puede deshabilitarlo configurando Pooling=false en su cadena de conexión).

Hay muchas cosas que podrían salir mal si intenta almacenar en caché la conexión usted mismo. Simplemente di no :)

+0

Lo que esperaba escuchar ... ¿Alguna idea sobre cómo podría reproducir el error exacto que estamos viendo? (solo para "probar" que he solucionado el problema) –

+0

Es difícil de decir, para ser honesto. Podría ser una condición de carrera si intentas usar la misma conexión desde múltiples hilos. –

+1

Para deshabilitar la agrupación de conexiones: agregue "Pooling = False;" a la cadena de conexión. – Richard

2

Deberías habilitar connection pooling en tu cadena de conexión. En ese caso, el tiempo de ejecución volverá a agregar sus conexiones al 'grupo' cuando las cierre, en lugar de desconectar realmente. Cuando se saca una conexión 'nueva' del grupo, se restablecerá (es decir, se llamará sp_reset_connection) y luego se presentará a su aplicación como una nueva conexión nueva. El grupo trata de forma transparente casos tales como si la conexión se cierra mientras está inactivo en el grupo.El costo de crear una nueva conexión 'desde cero' es significativo porque la autenticación requiere varios recorridos de ida y vuelta entre el cliente y el servidor (dependiendo del método de autenticación y de la configuración SSL, puede ser de 1 ida y vuelta en el mejor de los casos, alrededor de 10). peor).

Y para responder a su pregunta, la conexión plantea el evento OnStateChange cuando su estado cambia, pero no debería preocuparse por esto si utiliza la agrupación.

+0

La agrupación de conexiones es el valor predeterminado, no necesita hacer nada para habilitarlo. Puede desactivarlo, pero es un requisito poco común. – Richard

+1

Tenga en cuenta que si tiene habilitada la agrupación de conexiones y abre una conexión para verificar si existe una base de datos, y luego cree la base de datos en función de esta información. Entonces el truco sp_reset_connection no le permitirá ver la base de datos. Lo mismo ocurre con la primera conexión sin agrupación de conexiones. –

1

En mi experiencia reciente si se utiliza este código:

using(SQLConnection conn = new SQLConnection(connectionString)) 
{ 
    // do stuff with conn 
} 

tienen un error, y no cierran de forma explícita la conexión, no se cerrará o se comprueba de nuevo en la piscina. Entonces use un bloque catch o finally para cerrar la conexión

Cuestiones relacionadas