Истекло время ожидания Исключение; Не могу найти, какое соединение оставлено открытым или есть что-то еще не так - PullRequest
1 голос
/ 14 января 2012

Я получаю сообщение: «Время ожидания истекло. Период ожидания истек до получения соединения из пула. Это могло произойти, потому что все соединения в пуле использовались и был достигнут максимальный размер пула». ошибка, но не могу найти, где проблема. Маленькая помощь, пожалуйста. :)

public static void Update(string p, int c)
    {
        using (SqlConnection conn = new SqlConnection("ConnectionString"))
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataReader myRdr;

            cmd.Connection = conn;
            cmd.CommandText = "SOME SQL QUERY @parameter";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Add("@parameter", SqlDbType.NVarChar, 10).Value = p;

            conn.Open();
            myRdr = cmd.ExecuteReader();

            if (myRdr.HasRows)
            {
                while (myRdr.Read())
                {
                    //do something using myRdr data
                }
                myRdr.Close();
                cmd.Dispose();

                foreach (DataRow r in dt.Rows)
                {
                    SqlCommand cmd1 = new SqlCommand();

                    cmd1.Connection = conn;
                    cmd1.CommandText = "SOME SQL QUERY @parameter";
                    cmd1.CommandType = CommandType.Text;
                    cmd1.Parameters.Add("@parameter", SqlDbType.NVarChar, 10).Value = r["SomeData"];

                    myRdr = cmd1.ExecuteReader();
                    myRdr.Read();

                    //do something with myRdr data

                    myRdr.Close();
                    cmd1.Dispose();

                    int a = Convert.ToInt32(r["SomeData"]) - Convert.ToInt32(r["SomeData1"]);

                    if (a >= 0)
                    {
                        //do something
                    }
                    else
                    {
                        //do something else and runn the Update() again with some other parameters

                        Update(x, y); //I think here is some problem...
                                      //because when this condition is not met and program 
                                      //does not need to run Update() again, it goes OK and I get no error
                    }
                }
            }
            else
            {
                myRdr.Close();
                cmd.Dispose();
            }
        }
    }

Ответы [ 2 ]

3 голосов
/ 14 января 2012

Вы должны перемещать ваш вызов на Update(x,y) где-нибудь за пределами внешнего блока using().

Вызов его изнутри using означает, что вы устанавливаете другое соединение с той же базой данных без предварительного освобождения внешней. Если вы получаете количество рекурсивных вызовов, то у вас очень быстро заканчиваются бесплатные соединения.

Как правило, использование рекурсивных вызовов в частях кода, работающих с базами данных, считается очень плохой практикой.

Если вы ДЕЙСТВИТЕЛЬНО нуждаетесь в этой рекурсии здесь, то все же это должно быть сделано вне внешнего using. Я бы посоветовал кэшировать ваш x,y в какой-либо коллекции и отправлять вызовы на Update(x,y), пройдя эту коллекцию за пределами блока using, например:

public static void Update(string p, int c)
{
    // I'd suggest Dictionary, but don't know whether your strings are unique
    var recursionParameters = new List<KeyValuePair<string, int>>(); 

    using (SqlConnection conn = new SqlConnection("ConnectionString"))
    {
        ...
                    //do something else and runn the Update() again with some other parameters

                    //Update(x, y); Don't do it here! Instead:
                    recursionParameters.Add(new KeyValuePair<string, int>(x,y));
        ...
    }
    foreach (var kvp in recursionParameters
    {
        Update(kvp.Key, kvp.Value)
    }
}
1 голос
/ 14 января 2012

Ваш Reader не может быть закрыт при возникновении исключения.Окружите его блоком try finally, поэтому, когда вы встретите исключение, ваш читатель будет закрыт для оператора finally.

try
{  
    myRdr = cmd.ExecuteReader();
    // do some other stuff
}
catch(SqlException)
{
    // log the exception or deal with ex.

}
finally
{
    myRdr.Close(); // you can be sure it will be closed even on exception

}
...