Estou trabalhando em um projeto de criações de bots para automação de tarefas e estou enfrentando alguns problemas relacionados a timeout de conexao.
O banco de dados e SQL Server, toda a manipulação do banco está sendo feita a partir de procedures executadas por SQL Command, estou usando Using nas minhas conexoes e mesmo assim está dando timeout de conexao
Quando eu executo algumas vezes funciona porém lá na centésima vez ele estoura esta exception.
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached
STACKTRACE:
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() at RecepcaoBOT.DAO.RecepcaoDAO.AddTask(String task, String owner, String args) in R:\Informatica\Guilherme Maciel\PROJETOS\ETL BOT\CODIGO FONTE\ETL2\RecepcaoBOT\DAO\RecepcaoDAO.cs:line 136 at RecepcaoBOT.Negocio.Importador.OperatorFileImport.LoteImport(FileAttachment arquivo, ComandoEmail comando, EmailMessage email) in R:\Informatica\Guilherme Maciel\PROJETOS\ETL BOT\CODIGO FONTE\ETL2\RecepcaoBOT\Negocio\Importador\OperatorFileImport.cs:line 171 at RecepcaoBOT.Negocio.Importador.OperatorFileImport.BasicFilterImport(Int32 tarefa, ComandoEmail comando, EmailMessage email) in R:\Informatica\Guilherme Maciel\PROJETOS\ETL BOT\CODIGO FONTE\ETL2\RecepcaoBOT\Negocio\Importador\OperatorFileImport.cs:line 49 at RecepcaoBOT.Negocio.Importador.Importar.ImportarArquivo(Int32 tarefa, ComandoEmail comando, EmailMessage email) in R:\Informatica\Guilherme Maciel\PROJETOS\ETL BOT\CODIGO FONTE\ETL2\RecepcaoBOT\Negocio\Importador\Importar.cs:line 41 at RecepcaoBOT.Negocio.Atribuidor.AtribuirEmail(Int32 tarefa, ComandoEmail comando, EmailMessage email, String bodyComp) in R:\Informatica\Guilherme Maciel\PROJETOS\ETL BOT\CODIGO FONTE\ETL2\RecepcaoBOT\Negocio\Atribuidor.cs:line 70 at RecepcaoBOT.CORE.RecepcaoBot.Main(String[] args) in R:\Informatica\Guilherme Maciel\PROJETOS\ETL BOT\CODIGO FONTE\ETL2\RecepcaoBOT\CORE\RecepcaoBot.cs:line 79
Tenho uma classe chamada SQLConnectionFactory que pega a connectionString e cria uma SqlConnection fechada, o bug está dando quando eu chamo o .Open(), ele trava e lança excepion. Não sei se entendi muito bem o que tu quis dizer rs
internal class SQLConnectionFactory
{
//RETORNA CONEXAO COM O BANCO
public static SqlConnection getConnection()
{
return new SqlConnection(RecepcaoConfig.getInstance().Strcnn_lockton_inp);
}
}
Testei o seu code e mesmo assim não obtive exito, anteriormente eu fiz um teste com singleton utilizando uma única conexao e o erro persistiu, estou começando a pensar que é alguma configuração no Sql Server que está dando este erro, pois o mesmo ocorre no .Open() e também após um tempo executando diversos comandos em uma única conexao aberta.
Ai é o problema! não é no código, mas, a conexão com o banco não é fechada de imediato, e nem o objeto é é removido automáticamente com GC, isso tem um tempo para acontecer!
Como é chamado simultaneamente acontece esses problemas. Tem que fazer assim no método que você chama Add passar uma conexão com o banco e no final da iteração fechar no essa conexão.! Ou seja a conexão ficar aberta até ele acabar o for!
Vamos fazer um teste:
mude seu método assim:
public void AddTask(SqlConnection conexao, string task, string owner, string args)
{
LogIntegration.AddLog("Iniciando inserção de tarefa");
LogIntegration.AddLog(args);
try
{
using (SqlCommand comando = new SqlCommand("PROC_INSERT_TASK_TASK", conexao))
{
if (conexao.State == ConnectionState.Closed)
{
conexao.Open();
}
comando.CommandType = System.Data.CommandType.StoredProcedure;
comando.Parameters.AddWithValue("@TATY_TX_NAME", task);
comando.Parameters.AddWithValue("@USER_TX_EMAIL", owner);
comando.Parameters.AddWithValue("@TASK_TX_ARGS", args);
if (comando.ExecuteNonQuery() > 0)
{
LogIntegration.AddLog("Inserida com sucesso!");
}
}
}
catch (SqlException e)
{
LogIntegration.AddLog("Erro ao inserir tarefa : "+e.Message);
}
}
e no for:
using (SqlConnection conexao = SQLConnectionFactory.getConnection())
{
for(int i = 0; i < 1500; i++)
{
AddTask(conexao, task, owner, args);
}
}
Tipo mais ou menos assim, porque ai mesmo a conexão aberta com 1500 iterações ele vai utilizar 1 processo e resolver todas as SQL! Teste!?
não vai lançar uma exceção vai garantir que quando ele termine de usar a conexão ele faça o serviço todo inclusive devolvendo o recurso de conexão.
isso sempre deve ser utilizado quando vc utiliza recursos do tipo leitura de arquivo, download de arquivos e conexões de banco.