Saltar al contenido

ExecuteReader requiere una conexión abierta y disponible. El estado actual de la conexión es Conectando

Te traemos el hallazgo a este inconveniente, al menos eso deseamos. Si presentas interrogantes puedes dejarlo en el apartado de comentarios y sin pensarlo

Solución:

Perdón por solo comentar en primer lugar, pero publico casi todos los días un comentario similar ya que muchas personas piensan que sería inteligente encapsular la funcionalidad ADO.NET en una clase DB (yo también hace 10 años). En su mayoría, deciden usar static/objetos compartidos ya que parece ser más rápido que crear un nuevo objeto para cualquier acción.

Esa no es una buena idea en términos de rendimiento ni en términos de seguridad contra fallas.

No cace furtivamente en el territorio de Connection-Pool

Hay una buena razón por la que ADO.NET administra internamente las conexiones subyacentes al DBMS en el conjunto de conexiones de ADO-NET:

En la práctica, la mayoría de las aplicaciones utilizan solo una o unas pocas configuraciones diferentes para las conexiones. Esto significa que durante la ejecución de la aplicación, muchas conexiones idénticas se abrirán y cerrarán repetidamente. Para minimizar el costo de abrir conexiones, ADO.NET utiliza una técnica de optimización llamada agrupación de conexiones.

La agrupación de conexiones reduce la cantidad de veces que se deben abrir nuevas conexiones. El pooler mantiene la propiedad de la conexión física. Gestiona las conexiones manteniendo vivo un conjunto de conexiones activas para cada configuración de conexión dada. Cada vez que un usuario llama a Abrir en una conexión, el agrupador busca una conexión disponible en el grupo. Si hay una conexión agrupada disponible, se la devuelve a la persona que llama en lugar de abrir una nueva conexión. Cuando la aplicación llama a Cerrar en la conexión, el agrupador la devuelve al conjunto agrupado de conexiones activas en lugar de cerrarla. Una vez que la conexión se devuelve al grupo, está lista para ser reutilizada en la próxima llamada abierta.

Entonces, obviamente, no hay razón para evitar crear, abrir o cerrar conexiones, ya que en realidad no se crean, abren ni cierran en absoluto. Esta es “solo” una bandera para que el grupo de conexiones sepa cuándo se puede reutilizar una conexión o no. Pero es un indicador muy importante, porque si una conexión está “en uso” (se supone que el conjunto de conexiones), se debe abrir una nueva conexión física al DBMS, lo que es muy costoso.

Por lo tanto, no obtiene una mejora en el rendimiento, sino todo lo contrario. Si se alcanza el tamaño de grupo máximo especificado (100 es el valor predeterminado), incluso obtendrá excepciones (demasiadas conexiones abiertas…). Por lo tanto, esto no solo afectará enormemente el rendimiento, sino que también será una fuente de errores desagradables y (sin usar transacciones) un área de volcado de datos.

Si incluso estás usando static conexiones que está creando un bloqueo para cada subproceso que intenta acceder a este objeto. ASP.NET es un entorno multiproceso por naturaleza. Por lo tanto, existe una gran posibilidad de que estos bloqueos causen, en el mejor de los casos, problemas de rendimiento. En realidad, tarde o temprano obtendrá muchas excepciones diferentes (como su ExecuteReader requiere una conexión abierta y disponible).

Conclusión:

  • No reutilice las conexiones ni ningún objeto ADO.NET en absoluto.
  • no los hagas static/compartido(en VB.NET)
  • Siempre créelos, ábralos (en el caso de Conexiones), utilícelos, ciérrelos y deséchelos donde los necesite (por ejemplo, en un método)
  • utilizar el using-statement para disponer y cerrar (en el caso de Conexiones) implícitamente

Eso es true no solo para Conexiones (aunque más notable). Cada objeto que implementa IDisposable debe ser eliminado (más simple por using-statement), tanto más en el System.Data.SqlClient espacio de nombres

Todo lo anterior habla en contra de una DB-Class personalizada que encapsula y reutiliza todos los objetos. Esa es la razón por la que comenté para tirarlo a la basura. Eso es solo una fuente de problemas.


Editar: Aquí hay una posible implementación de su retrievePromotion-método:

public Promotion retrievePromotion(int promotionID)

    Promotion promo = null;
    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MainConnStr"].ConnectionString;
    using (SqlConnection connection = new SqlConnection(connectionString))
    
        var queryString = "SELECT PromotionID, PromotionTitle, PromotionURL FROM Promotion WHERE [email protected]";
        using (var da = new SqlDataAdapter(queryString, connection))
        
            // you could also use a SqlDataReader instead
            // note that a DataTable does not need to be disposed since it does not implement IDisposable
            var tblPromotion = new DataTable();
            // avoid SQL-Injection
            da.SelectCommand.Parameters.Add("@PromotionID", SqlDbType.Int);
            da.SelectCommand.Parameters["@PromotionID"].Value = promotionID;
            try
            
                connection.Open(); // not necessarily needed in this case because DataAdapter.Fill does it otherwise 
                da.Fill(tblPromotion);
                if (tblPromotion.Rows.Count != 0)
                
                    var promoRow = tblPromotion.Rows[0];
                    promo = new Promotion()
                    
                        promotionID    = promotionID,
                        promotionTitle = promoRow.Field("PromotionTitle"),
                        promotionUrl   = promoRow.Field("PromotionURL")
                    ;
                
            
            catch (Exception ex)
            
                // log this exception or throw it up the StackTrace
                // we do not need a finally-block to close the connection since it will be closed implicitely in an using-statement
                throw;
            
        
    
    return promo;

Recuerda mostrar esta reseña si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *