2012-01-12 78 views
2

我有一个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+配置文件。 它似乎就像我正在做的一切正确,但我不知道为什么连接不会被释放回池中。在大多数应该只有两个连接被执行线程打开,这两个连接应该(并且!)在它们超出范围时处置。

我明显做错了事,但不能为我的生活找出什么。

+0

显然,东西不打烊的地方应该是。尝试在Connection上的清理代码之前移动Command对象上的清理代码。如果你正在使用它们,也是DataAdapters。 – LarsTech 2012-01-12 21:07:44

+0

@LarsTech,似乎有帮助,我不能再现错误了,但做了改变和重新部署,但我希望我能更好地理解发生了什么。 – 2012-01-12 21:19:30

回答

4

从我的评论,我会转换为答案。

看起来你正试图在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(); 
} 
1

如果我没有记错,SqlHelper dispose不会自动关闭连接。你需要明确地关闭它。

我们总是在try/finally中使用SqlHelper,并在finally中显式调用close。

+0

我通常使用标题“SqlHelper”来描述我使用的包装类。代码在析构函数中的SqlConnection上调用'.Close()',当我们验证的对象超出了using语句的范围时,我正在调用它。 – 2012-01-12 21:05:29

+0

啊,好的。我认为这是来自MS企业库(这是我们使用的)。 – 2012-01-12 21:22:00