Ao tentar se conectar ao banco de dados MSSQL via ASP.NET online, obtenho o seguinte quando duas ou mais pessoas se conectam simultaneamente:
ExecuteReader requer uma conexão aberta e disponível. O estado atual da conexão é Conectando.
O site funciona bem no meu servidor localhost.
Este é o 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;
}
Posso saber o que pode ter dado errado e como faço para corrigir isso?
Edit: para não esquecer, minha string de conexão e conexão são estáticas. Acredito que seja esse o motivo. Por favor informar.
public static string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
public static SqlConnection conn = null;
c#
.net
sql-server
ado.net
database-connection
Guo Hong Lim
fonte
fonte
conString
não acrescenta nada em termos de desempenho, já que é armazenado em cache por padrão de qualquer maneira (como todo valor de configuração para o aplicativo atual).Respostas:
Desculpe por apenas comentar em primeiro lugar, mas estou postando quase todos os dias um comentário semelhante, já que muitas pessoas pensam que seria inteligente encapsular a funcionalidade ADO.NET em uma classe de banco de dados (eu também há 10 anos). Principalmente, eles decidem usar objetos estáticos / compartilhados, pois parece ser mais rápido do que criar um novo objeto para qualquer ação.
Isso não é uma boa ideia em termos de desempenho nem em termos de segurança contra falhas.
Não roube o território do Connection-Pool
Há um bom motivo pelo qual o ADO.NET gerencia internamente as conexões subjacentes ao DBMS no pool de conexões ADO-NET :
Obviamente, não há razão para evitar a criação, abertura ou fechamento de conexões, pois, na verdade, elas não são criadas, abertas e fechadas. Este é "apenas" um sinalizador para o pool de conexão saber quando uma conexão pode ser reutilizada ou não. Mas é um sinalizador muito importante, porque se uma conexão está "em uso" (o pool de conexão assume), uma nova conexão física deve ser aberta para o DBMS, o que é muito caro.
Portanto, você não está obtendo melhoria de desempenho, mas o oposto. Se o tamanho máximo do pool especificado (100 é o padrão) for atingido, você poderá até obter exceções (muitas conexões abertas ...). Portanto, isso não só afetará tremendamente o desempenho, mas também será uma fonte de erros desagradáveis e (sem usar transações) uma área de despejo de dados.
Se você estiver usando conexões estáticas, estará criando um bloqueio para cada thread que tentar acessar este objeto. ASP.NET é um ambiente multithreading por natureza. Portanto, há uma grande chance para esses bloqueios, o que causa, na melhor das hipóteses, problemas de desempenho. Na verdade, mais cedo ou mais tarde você terá muitas exceções diferentes (como o ExecuteReader requer uma conexão aberta e disponível ).
Conclusão :
using-statement
para descartar e fechar (no caso de conexões) implicitamenteIsso é verdade não apenas para Conexões (embora seja mais perceptível). Cada objeto implementado
IDisposable
deve ser descartado (mais simples porusing-statement
), ainda mais noSystem.Data.SqlClient
namespace.Tudo o que foi dito acima fala contra uma classe de banco de dados personalizada que encapsula e reutiliza todos os objetos. Essa é a razão pela qual eu comentei para o lixo. Essa é apenas uma fonte de problema.
Edit : Aqui está uma possível implementação de seu
retrievePromotion
-método:fonte
Eu peguei esse erro alguns dias atrás.
No meu caso, foi porque eu estava usando uma Transação em um Singleton.
.Net não funciona bem com o Singleton conforme declarado acima.
Minha solução foi esta:
Usei HttpContext.Current.Items para minha instância. Esta classe DbHelper e DbHelperCore é minha própria classe
fonte