简体   繁体   中英

Running out of connections in pool

I have a web forms app that will display a list of records in a GridView and by checking multiple checkboxes you can mass delete the records. The code itself is straightforward:

protected void btnDelete_Click(object sender, EventArgs e)
{
    int i = 0;
    try
    {
        foreach (GridViewRow row in GridView1.Rows)
        {
            CheckBox cb = (CheckBox)row.FindControl("ID");
            if (cb != null && cb.Checked)
            {
                int profileID = Convert.ToInt32(GridView1.DataKeys[row.RowIndex].Value);
                Profile profile = new Profile(profileID); //instantiate profile
                profile.Delete(); //call delete method
                i++;
            }
        }
        if (i > 0)
        {
            //report success to UI
        }
    }
    catch (Exception ex)
    {
        //report error to UI
    }
}

In the profile constructor, it hydrates the object by opening up a connection, opening a datareader and then setting the properties of the object. I am meticulous about using() blocks in my code so every db connection looks about like this:

using (SQLHelper db = new SQLHelper())
{
    db.AddParameterToSQLCommand("@ProfileID", SqlDbType.Int);
    db.SetSQLCommandParameterValue("@ProfileID", id);

    using (SqlDataReader dr = db.GetReaderByCmd("up_GetProfile"))
    {
        if (dr.Read())
        {
            _profileID = id;
            if (!dr.IsDBNull(0))
                ProfileName = dr.GetString(0);
            //... and so on
            return true;
        }
        else
        {
            return false;
        }
    }
}

A datareader implements iDisposible, as does my helper class, and the destructor looks like this:

public void Dispose()
{
    try
    {
        //Clean Up Connection Object
        if (mobj_SqlConnection != null)
        {
            if (mobj_SqlConnection.State != ConnectionState.Closed)
            {
                mobj_SqlConnection.Close();
            }
            mobj_SqlConnection.Dispose();
        }

        //Clean Up Command Object
        if (mobj_SqlCommand != null)
        {
            mobj_SqlCommand.Dispose();
        }
    }

    catch (Exception ex)
    {
        throw new Exception("Error disposing data class." + Environment.NewLine + ex.Message);
    }
}

When I step through my code I see that connections are always being opened and closed correctly, my stack is never more than five or six calls deep (I'm not running into any recursion problems) I have confirmed that all my data access code is correctly wrapped in using blocks yet my connections aren't being released back to the pool. Instead I get this error:

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.

This happens in a dedicated app pool with a single user effecting a delete on 10+ profiles. It seems like I'm doing everything correctly but I am at a loss as to why connections are not being released back to the pool. At most there should only ever be two connections open by the executing thread, both of which should (and do!) dispose when they go out of scope.

I'm clearly doing something wrong but can't for the life of me figure out what.

From my comment, I'll convert to an answer.

It looks like you are trying to close your Connection objects before the Command objects, and since the Command objects reference a connection, it might be keeping the connection alive.

Try switching them around:

//Clean Up Command Object
if (mobj_SqlCommand != null)
{
  mobj_SqlCommand.Dispose();
}

if (mobj_SqlConnection != null)
{
  if (mobj_SqlConnection.State != ConnectionState.Closed)
  {
    mobj_SqlConnection.Close();
  }
  mobj_SqlConnection.Dispose();
}

If I remember correctly, SqlHelper dispose does not automatically close the connection. You need to explicitly close it.

We always wrap our usage of SqlHelper in a try/finally and explicitly call close in the finally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM