2012-01-12 7 views
2

私は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を開くと、オブジェクトのプロパティを設定することにより、オブジェクトを水和します。私は、すべてのDB接続は次のように程度になります私のコードで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); 
    } 
} 

私のコードをステップ実行すると、接続が常に開かれ、正しく閉じられていることがわかります。私のスタックは5,6コール以上深くはありません(再帰の問題は発生していません)。ブロックを使用して正しくラップされますが、私の接続はプールに戻されません。代わりに私はこのエラーを受け取ります:

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以上のプロファイルで削除を実行する専用アプリケーションプールで発生します。 は、私がすべてを正しくしているように、と思われますが、なぜ接続がプールに戻されていないのかが分かりません。 の場合、ほとんどの場合、は実行スレッドによって2つの接続がオープンされているだけで、どちらもスコープ外に出たときに処分する必要があります。

私は明らかに何か間違っていますが、私の人生にとっては何が分かりませんか。

+0

それがあるべき場所、何かがクローズされていません。 Connection上のコードをクリーンアップする前に、そのクリーンアップコードをCommandオブジェクト上に移動してみてください。また、それらを使用している場合はDataAdapters。 – LarsTech

+0

@LarsTechが助けてくれたようだが、その変更と再デプロイ後にエラーを再現することはできない。 –

答えて

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は接続を自動的に終了しません。あなたは明示的にそれを閉じる必要があります。

私たちは常にSqlHelperの使用方法をtry/finallyでラップし、最後に明示的にcloseを呼び出します。

+0

私は、 "SqlHelper"というタイトルを使用して、私が使用するラッパークラスを一般的に記述しています。コードは、オブジェクトがusingステートメントのスコープ外に出たときに、私が検証したデストラクタのSqlConnectionで '.Close()'を呼び出すことが正しく呼び出されています。 –

+0

ああ、大丈夫です。私はそれがMSのエンタープライズライブラリ(これが私たちが使用しているもの)のものだと思った。 –

関連する問題