Al intentar conectarme a la base de datos MSSQL a través de ASP.NET en línea, obtendré lo siguiente cuando dos o más personas se conecten simultáneamente:
ExecuteReader requiere una conexión abierta y disponible. El estado actual de la conexión es Conectando.
El sitio funciona bien en mi servidor localhost.
Este es el código aproximado.
public Promotion retrievePromotion()
{
int promotionID = 0;
string promotionTitle = "";
string promotionUrl = "";
Promotion promotion = null;
SqlOpenConnection();
SqlCommand sql = SqlCommandConnection();
sql.CommandText = "SELECT TOP 1 PromotionID, PromotionTitle, PromotionURL FROM Promotion";
SqlDataReader dr = sql.ExecuteReader();
while (dr.Read())
{
promotionID = DB2int(dr["PromotionID"]);
promotionTitle = DB2string(dr["PromotionTitle"]);
promotionUrl = DB2string(dr["PromotionURL"]);
promotion = new Promotion(promotionID, promotionTitle, promotionUrl);
}
dr.Dispose();
sql.Dispose();
CloseConnection();
return promotion;
}
¿Puedo saber qué pudo haber salido mal y cómo lo soluciono?
Editar: sin olvidar, mi cadena de conexión y mi conexión son estáticas. Creo que esta es la razón. Por favor avise.
public static string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
public static SqlConnection conn = null;
c#
.net
sql-server
ado.net
database-connection
Guo Hong Lim
fuente
fuente
conString
no agrega nada en términos de rendimiento, ya que de todos modos se almacena en caché de forma predeterminada (como todos los valores de configuración para la aplicación actual).Respuestas:
Lo siento por solo comentar en primer lugar, pero estoy publicando casi todos los días un comentario similar ya que muchas personas piensan que sería inteligente encapsular la funcionalidad de ADO.NET en una DB-Class (yo también hace 10 años). En su mayoría, deciden usar objetos estáticos / 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 caza 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 grupo de conexiones de ADO-NET :
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 una conexión se puede reutilizar o no. Pero es una bandera muy importante, porque si una conexión está "en uso" (asume el grupo de conexiones), se debe abrir una nueva conexión física al DBMS, lo que es muy costoso.
Por lo tanto, no obtiene ninguna mejora en el rendimiento, sino todo lo contrario. Si se alcanza el tamaño máximo de grupo especificado (100 es el predeterminado), incluso obtendría excepciones (demasiadas conexiones abiertas ...). Por lo tanto, esto no solo afectará enormemente al rendimiento, sino que también será una fuente de errores desagradables y (sin usar Transacciones) un área de descarga de datos.
Si incluso está utilizando conexiones estáticas, está creando un bloqueo para cada hilo que intente acceder a este objeto. ASP.NET es un entorno de subprocesos múltiples por naturaleza. Así que hay una gran posibilidad de que estos bloqueos provoquen problemas de rendimiento en el mejor de los casos. En realidad, tarde o temprano obtendrá muchas excepciones diferentes (como que su ExecuteReader requiere una conexión abierta y disponible ).
Conclusión :
using-statement
para eliminar y cerrar (en caso de conexiones) implícitamenteEso es cierto no solo para Connections (aunque es más notable). Cada objeto que se implemente
IDisposable
debe eliminarse (más simple porusing-statement
), más aún en elSystem.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é que lo tirara a la basura. Esa es solo una fuente de problemas.
Editar : Aquí hay una posible implementación de su
retrievePromotion
método:fuente
Cogí este error hace unos días.
EN mi caso fue porque estaba usando una Transacción en un Singleton.
.Net no funciona bien con Singleton como se indicó anteriormente.
Mi solución fue esta:
Usé HttpContext.Current.Items para mi instancia. Esta clase DbHelper y DbHelperCore es mi propia clase
fuente