2012-01-12 11 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를 열고 그 오브젝트의 속성을 설정하여 객체를 촉촉. 난 내 코드에서 using() 블록에 대한 세심한 그래서 모든 DB 연결이 같은 대한 보인다 이니

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 콜을 넘지 않습니다. (모든 재귀 문제가 발생하지 않습니다.) 모든 데이터 액세스 코드가 올바르게 블록으로 묶여 있지만 연결은 풀로 다시 릴리스되지 않습니다. 대신이 오류를 얻을 : 이것은이 10 명 + 프로필을 삭제 초래 한 사용자와 전용 응용 프로그램 풀에서 발생

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. 

합니다. 은 내가 올바르게 모든 것을하고있는 것처럼 인 것 같습니다. 그러나 연결이 풀에 다시 릴리스되지 않는 이유는 무엇입니까? 에서 대부분은 실행 스레드에 의해 열린 두 개의 연결이어야합니다. 둘 다 범위를 벗어나면 처분해야합니다.

나는 분명히 잘못된 일을하고 있지만 내 삶을 위해 할 수없는 것은 무엇인지 알아 낸다.

+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가 자동으로 연결을 닫지 않습니다. 명시 적으로 닫아야합니다.

우리는 항상 try/finally에서 SqlHelper의 사용법을 포장하고 finally에서 close를 명시 적으로 호출합니다.

+0

"SqlHelper"라는 제목을 사용하여 일반적으로 사용하는 래퍼 클래스를 설명합니다. 이 코드는 객체가 using 문에서 벗어 났을 때 올바르게 호출되고있는 소멸자의 SqlConnection에서'.Close()'를 호출하고 있습니다. –

+0

아, 좋아. MS 엔터프라이즈 라이브러리 (이 라이브러리가 우리가 사용하는 라이브러리) 중 하나라고 생각했습니다. –

관련 문제