簡體   English   中英

池中的連接用完

[英]Running out of connections in pool

我有一個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
    }
}

在配置文件構造函數中,它通過打開連接,打開數據讀取器然后設置對象的屬性來水合對象。 我對代碼中的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;
        }
    }
}

數據讀取器實現了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處理不會自動關閉連接。 您需要顯式關閉它。

我們總是在try / final中包裝SqlHelper的用法,並在finally中顯式調用close。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM