por Cesar Cassiano Schimanco

Problemas com MySQL connections pool - ASP.NET / C#

Quando falamos de SQL Server e ExecuteReader, usamos o CommandBehavior.CloseConnection para fechar a conexão após usar o DataReader.

SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

No MySQL o CommandBehavior.CloseConnection não funciona se não der Dispose() no MySqlDataReader e gerará o seguinte erro:

Server Error in '/' Application.

error connecting: 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.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: MySql.Data.MySqlClient.MySqlException: error connecting: 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.

A forma correta é dar Dispose() depois de utilizar o MySqlDataReader, isso vai fazer com que a conexão seja fechada e consequentemente não vai gerar nenhum tipo de erro.

protected void Page_Load(object sender, EventArgs e)
{
    //for para forçar 100 conexões
    for (int i = 0; i < 100; i++)
    {
        //Chamar o reader com a query de consulta
        MySqlDataReader dr = reader("SELECT COUNT(*) FROM tblUsers");
        //Responder na tela os valores
        while (dr.Read())
            Response.Write(dr.GetString(0));
            
        //Liberar o objeto MySqlDataReader para fechar a conexão.
        dr.Dispose();
    }
}

private MySqlDataReader reader(string sql)
{
    MySqlConnection conn = new MySqlConnection(Settings.ConnectionString);
    //Criando o MySqlCommand como a query e a conexão
    MySqlCommand cmd = new MySqlCommand(sql, conn);
    //Abrir a conexão
    conn.Open();
    //Popular o MySqlDataReader com os dados da consulta
    MySqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    //Retornar o MySqlDataReader
    return dr;
}

Um erro comum é tentar fechar a conexão antes de usar o MySqlDataReader, como no exemplo abaixo.

protected void Page_Load(object sender, EventArgs e)
{
    //for para forçar 100 conexões
    for (int i = 0; i < 100; i++)
    {
        //Chamar o reader com a query de consulta
        MySqlDataReader dr = reader("SELECT COUNT(*) FROM tblUsers");
        //Responder na tela os valores
        while (dr.Read())
            Response.Write(dr.GetString(0));
    }
}

private MySqlDataReader reader(string sql)
{
    //Criar a conexão com o banco de dados
    MySqlConnection conn = new MySqlConnection(Settings.ConnectionString);
    //Criando o MySqlCommand como a query e a conexão
    MySqlCommand cmd = new MySqlCommand(sql, conn);
    //Abrir a conexão
    conn.Open();
    //Popular o MySqlDataReader com os dados da consulta
    MySqlDataReader dr = cmd.ExecuteReader();
    //fechar a conexão
    conn.Close();
    //Retornar o MySqlDataReader
    return dr;
}

Este código vai gerar o seguinte erro:

Server Error in '/' Application.

Invalid attempt to Read when reader is closed.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: MySql.Data.MySqlClient.MySqlException: Invalid attempt to Read when reader is closed.

Se quiser limpar o Pool do MySQL, use o MySqlConnection.ClearPool(conn), lembrando de dar Dispose no MySqlDataReader, isso também funciona.
Veja o exemplo abaixo:
 

protected void Page_Load(object sender, EventArgs e)
{
    //for para forçar 100 conexões
    for (int i = 0; i < 100; i++)
    {
        //Chamar o reader com a query de consulta
        MySqlDataReader dr = reader("SELECT COUNT(*) FROM tblUsers");
        //Responder na tela os valores
        while (dr.Read())
            Response.Write(dr.GetString(0));
            
        //Liberar o objeto MySqlDataReader, se não liberar o dr, não vai limpar o Pool.
        dr.Dispose();
    }
}

private MySqlDataReader reader(string sql)
{
    MySqlConnection conn = null;
    try
    {
        //Criar a conexão com o banco de dados
        conn = new MySqlConnection(Settings.ConnectionString);
        //Criando o MySqlCommand como a query e a conexão
        MySqlCommand cmd = new MySqlCommand(sql, conn);
        //Abrir a conexão
        conn.Open();
        //Popular o MySqlDataReader com os dados da consulta
        MySqlDataReader dr = cmd.ExecuteReader();
        //Retornar o MySqlDataReader
        return dr;
    }
    finally
    {
        MySqlConnection.ClearPool(conn);
    }
}

 

Comentários

Carregando comentários

Postar um novo comentário



Processando...