2012-01-26 2 views
7

이것은 내가 가지고있는 코드입니다.이 명령과 관련된 열려있는 DataReader가 이미 있습니다. 먼저 닫아야합니다.

/// <summary> 
/// Method calls stored procedure and fills DataSet of contacts associated with Lead 
/// </summary> 
/// <param name="leadID">The ID associated with a Lead</param> 
/// <returns>contacts list as DataSet</returns> 
public static DataSet GetContactResultSetByLead(int leadID) 
{ 
    SqlCommand Sqlmd = new SqlCommand("dbo.proc_contact"); 
    Sqlmd.CommandType = CommandType.StoredProcedure; 
    Sqlmd.Parameters.Add("@LeadInfoID", SqlDbType.Int).Value = leadID; 

    Sqlmd.Connection = m_ConStr; 
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd); 

    DataSet data = new DataSet(); 
    try 
    { 
     da.Fill(data); 
    } 

    finally 
    { 
     m_ConStr.Close(); 
    } 

    return data; 
} 
+0

'm_ConStr'이란 무엇입니까? –

+0

이 줄 바꾸기 Sqlmd.Parameters.Add ("@ LeadInfoID", SqlDbType.Int) .Value = leadID; Sqlmd.Parameters.AddWithValue ("@ LeadInfoID", leadID); 글로벌 연결을 유지하려면 연결 상태를 확인한 다음 사용하기 전에 닫습니다. 귀하의 코드를 재 설계하고 의미있는 이름을 사용하십시오 ....! using() {} – MethodMan

+1

주위에 연결 랩 Sqlmd는 da.Fill 호출 중에 실행됩니다. m_ConStr은 이름이 잘못 지정된 변수처럼 보입니다. 연결 문자열이 아닌 연결 자체를 나타냅니다. – RQDQ

답변

9

문제는 분명히 하나의 인스턴스가 m_ConStr 인 것입니다. 메서드가 동시에 호출되는 경우 그 중 하나만 연결을 사용할 수 있고 다른 하나는 수신중인 예외와 함께 실패합니다.

사용하는 대신이 패턴 : 다른 말로

using (SqlConnection conn = new SqlConnection()) 
{ 
    conn.Open(); 
    Sqlmd.Connection = conn; 
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd); 
    //...etc 
} 

는 클래스에 전역 변수로 연결을 정의하지 않습니다.

+0

"연결을 전역 변수로 정의하지 마십시오." 내가 sp를 실행해야 할 때마다 연결을 만들고 엽니 다. 제 경우에는 많은 sp를 실행해야하고, 연결을 인스턴스화하지 않고 대안을 만들고 매번 열어야합니다. 어떤 힌트? – ff8mania

1

여러 개의 액티비티 결과 세트 (별칭 MARS)를 실행하려고합니다.

두 가지 가능한 솔루션은 마음에 와서 :

  1. 열기
  2. 은 (위의 링크 참조) 데이터베이스 서버에 MARS를 사용하여 GetContractResultSetByLead에서 새 연결을 엽니 다.
+0

또한이 값을 web.config의 연결 문자열에 추가 할 수 있습니다. connectionString = "MultipleActiveResultSets = True; user = ..." – Nestor

5

나는 블록을 사용하여 sqlconnection을 올바르게 폐기 할 수 있다고 제안합니다.

using (SqlConnection conn = new SqlConnection()) 
{ 
    conn.Open(); 
    Sqlmd.Connection = conn; 
    SqlDataAdapter da = new SqlDataAdapter(Sqlmd); 
    Dataset ds = new Datasest 
    da.Fill(ds) 
} 

다른 방법으로 필요한 경우 연결에 MARS 속성을 설정할 수도 있습니다.

SqlConnection m_ConStr;= new SqlConnection("Server= serverName;Database=yourDatabase; 
     MultipleActiveResultSets=true;"); 
+2

연결을 로컬로 선언해야합니다 (공유 인스턴스를 사용하는 경우 모든 종류의 부작용이 발생합니다). 또한 연결의 수명을 관리하기 위해 using 문을 사용하지 않는 이유는 무엇입니까? – RQDQ

+1

도 좋은 제안 :) 확인 편집 할 것입니다 :) –

+1

대단히 감사합니다 – Marcus3329

5

수명이 짧은 IDisposable 개체에는 "사용 중"이 없습니다. 확장 기능을 사용하면 다음과 같은 작업을 수행 할 수 있습니다.

var reader = anotherCommand.ExecuteReader(); 
... 

하지만 리더기를 처분하거나 닫지는 않습니다. 이 경우 "사용"을 추가 : 독자를 닫

using(var reader = anotherCommand.ExecuteReader()) { 
    ... 
} 

을, 상관없이 어떻게 출구의. 명령, 연결, 판독기 및 트랜잭션은 모두 일회용이며 일반적으로 모두 "사용"해야합니다.