Timeout expired Exception; Can't find which connection is left open or if there is something else wrong

StackOverflow https://stackoverflow.com/questions/8863003

  •  28-10-2019
  •  | 
  •  

Question

I'm getting "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." error, but can't find where is the problem. Little help, please. :)

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();
            }
        }
    }
Was it helpful?

Solution

You should cosider moving your call to Update(x,y) somewhere outside the outer using() block.

Calling it from the inside using means you're establishing another connection to the same database without first freeing the outer one. If you get number of recursive calls then you'll run out of free connections VERY quickly.

In general, using recursion calls in parts of code dealing with databases is considered a very bad practice.

If you REALLY need this recursion here then still it should be done outside the outer using. I'd suggest caching your x,y in some kind of collection and issuing the calls to Update(x,y) by traversing this collection outside the using block, like this :

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)
    }
}

OTHER TIPS

Your Reader may not be closed when exception occurs. Surround it with try finally block, so when you meet exception your reader will be closed on finally statement.

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

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top