池中的连接用尽
我有一个Web表单应用程序,它将显示GridView中的记录列表,并通过选中多个复选框来批量删除记录。代码本身很简单:池中的连接用尽
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
}
}
在配置文件构造,它水合物通过打开的连接,打开一个DataReader,然后设置对象的属性的对象。我一丝不苟在我的代码using()
块,这样每一个数据库连接看起来大约是这样的:
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;
}
}
}
一个DataReader实现iDisposible一样,我的辅助类和析构函数如下:
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);
}
}
当我遍历我的代码时,我发现连接总是正确地打开和关闭,我的堆栈永远不会超过五或六个调用深度(我没有遇到任何递归问题)我已确认我的所有数据访问代码是使用块正确包装,但我的连接没有被释放回池中。相反,我得到这个错误:
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+配置文件。 它似乎就像我正在做的一切正确,但我不知道为什么连接不会被释放回池中。在大多数应该只有两个连接被执行线程打开,这两个连接应该(并且!)在它们超出范围时处置。
我明显做错了事,但不能为我的生活找出什么。
从我的评论,我会转换为答案。
看起来你正试图在Command对象之前关闭Connection对象,并且由于Command对象引用了一个连接,它可能会使连接保持活动状态。
尝试围绕切换它们:
//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();
}
如果我没有记错,SqlHelper dispose不会自动关闭连接。你需要明确地关闭它。
我们总是在try/finally中使用SqlHelper,并在finally中显式调用close。
我通常使用标题“SqlHelper”来描述我使用的包装类。代码在析构函数中的SqlConnection上调用'.Close()',当我们验证的对象超出了using语句的范围时,我正在调用它。 – 2012-01-12 21:05:29
啊,好的。我认为这是来自MS企业库(这是我们使用的)。 – 2012-01-12 21:22:00
显然,东西不打烊的地方应该是。尝试在Connection上的清理代码之前移动Command对象上的清理代码。如果你正在使用它们,也是DataAdapters。 – LarsTech 2012-01-12 21:07:44
@LarsTech,似乎有帮助,我不能再现错误了,但做了改变和重新部署,但我希望我能更好地理解发生了什么。 – 2012-01-12 21:19:30