池中的连接用完 [英] Running out of connections in pool

查看:35
本文介绍了池中的连接用完的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Web 表单应用程序,它将在 GridView 中显示记录列表,通过选中多个复选框,您可以批量删除记录.代码本身很简单:

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

在配置文件构造函数中,它通过打开连接、打开数据读取器然后设置对象的属性来对对象进行水合.我对代码中的 using() 块非常谨慎,所以每个数据库连接看起来像这样:

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

数据读取器实现了 iDisposible,就像我的助手类一样,析构函数看起来像这样:

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

当我逐步执行我的代码时,我看到连接总是被正确打开和关闭,我的堆栈从不超过五六个调用深度(我没有遇到任何递归问题)我已经确认我的所有数据访问代码正确地包含在 using 块中,但我的连接没有被释放回池中.相反,我收到此错误:

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.

这发生在一个专用应用程序池中,单个用户对 10 多个配置文件进行删除.似乎我做的一切都是正确的,但我不知道为什么连接没有被释放回池.在大多数,执行线程应该只打开两个连接,当它们超出范围时,这两个连接都应该(并且确实!)处理.

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.

看起来您正在尝试在关闭 Command 对象之前关闭 Connection 对象,并且由于 Command 对象引用了一个连接,因此它可能会保持连接处于活动状态.

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.

尝试切换它们:

//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();
}

这篇关于池中的连接用完的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆