2012-11-19 2 views
1

첫 번째 연결에서 많은 데이터 (수천 개의 행)가 반환되는 다음 코드 (여기서는 가독성을 위해 가독성이 있음)가 있습니다. ,"리더가 닫힐 때 Read 호출을 잘못 시도했습니다."

[InvalidOperationException: Invalid attempt to call Read when reader is closed.] 
System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) +640 
System.Data.SqlClient.SqlDataReader.Read() +9 

잘 작동 개발 환경에서 : SqlDataReader 개체는 그들에게 reader.Read() 하나 하나를 읽은 다음 새 값으로 각 행을 업데이트 할 새 연결을 엽니 다

using (SqlConnection conn = new SqlConnection(connString)) 
    using (SqlCommand cmd = new SqlCommand("sp1", conn)) 
    { 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.AddWithValue("@param1", param1); 
     cmd.Connection.Open(); 
     using (SqlDataReader reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       try 
       { 
        string hash= utils.SHA256.Hashing((string)reader["firstRow"], saltValue); 
        using (SqlConnection conn2 = new SqlConnection(connString)) 
        using (SqlCommand cmd2 = new SqlCommand("sp2", conn2)) 
        { 
         cmd2.CommandType = CommandType.StoredProcedure; 
         cmd2.Parameters.AddWithValue("@param1", param1); 
         cmd2.Parameters.AddWithValue("@param2", param2); 
         cmd2.Connection.Open(); 
         cmd2.ExecuteNonQuery(); 
        } 
       } 
       catch (SqlException ex) 
       { 
        //something 
       } 
      } 
     } 
    } 

를하지만 오류가 발생합니다 하지만 여기에는 몇 백 줄 밖에 없습니다. 그것은 즉시 오류를 던져 버리기 때문에 어떤 종류의 시간 초과처럼 보이지는 않습니다.하지만 헤이 - 잘 모르겠습니다 ...

+0

어떤 라인이 실패합니까? – CodingGorilla

+0

리더에서 읽기를 호출 할 때. while (reader.Read()) – Thomas

+0

첫 번째 SPROC에서 SQL로이 작업을 수행 할 수 있습니까? – MikeSmithDev

답변

5

왜 그런지 모르지만 실행하는 것은 정말 좋은 생각입니다. 동일한 데이터베이스에 대한 실시간 연결을 반복하면서 쿼리합니다. DataReader를 사용하여 레코드를 반복하는 한 연결이 살아 있음을 명심하십시오.

매우 열악한 것은 개를 열어서 번 연결을 빠르게 연속하여 수천 번 반복합니다. 이것은 혼자서 모든 데이터베이스를 무릎까지 가져올 수 있습니다.

로직을 변경하고 필요한 값을 로컬 변수 (구조는 중요하지 않음)에 저장 한 다음 하나의 연결 만 사용하여 필요한 모든 저장 프로 시저를 실행하십시오. 예를 들어

:

using (SqlConnection conn = new SqlConnection(connString)) 
{ 
    conn.Open(); 

    List<string[]> values = new List<string[]>(); 
    using (SqlCommand cmd = new SqlCommand("sp1", conn)) 
    { 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.AddWithValue("@param1", param1); 
     using (SqlDataReader reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       try 
       { 
        string hash= utils.SHA256.Hashing((string)reader["firstRow"], saltValue); 
        string anotherValue = (string)reader["secondRow"]; 
        values.Add(new string[] { hash, anotherValue }); 
       } 
       catch (SqlException ex) 
       { 
        //something 
       } 
      } 
      reader.Close(); 
     } 
    } 

    if (values.Count > 0) 
    { 
     using (SqlCommand cmd2 = new SqlCommand("sp2", conn)) 
     { 
      cmd2.CommandType = CommandType.StoredProcedure; 
      cmd2.Parameters.AddWithValue("@param1", null); 
      cmd2.Parameters.AddWithValue("@param2", null); 
      values.ForEach(items => 
      { 
       cmd2.Parameters["@param1"].Value = items[0]; 
       cmd2.Parameters["@param2"].Value = items[1]; 
       cmd2.ExecuteNonQuery(); 
      }); 
     } 
    } 
    conn.Close(); 
} 

한 연결은 하나의 명령은 모든 저장 프로 시저를 실행한다. 정말 그 이상은 필요하지 않습니다.

+3

"연결을 닫은 후 수 천을 닫습니다"는 연결 풀링을 사용하는 경우 매우 저렴합니다. –

+0

감사합니다. 약간 재 작성했지만 꽤 많이 이것을 따라갔습니다 - 그리고 그것은 효과가있었습니다 ... 여전히 오류에 대해서는 알지 못하지만 희망을 갖고 다시는 보지 않을 것입니다! – Thomas

+0

건배 @Thomas 데이터베이스에 과부하가 발생하여 내부 시간 제한이 발생하여 DataReader가 닫혔습니다. 이제 여분의 과부하가 발생하지 않으므로 발생하지 않습니다. :) –

관련 문제