2012-01-12 82 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