2017-01-31 3 views
0

현재 여러 방법으로 하나의 메서드로 여러 SqlDataReader 및 명령에 문제가 있습니다. 이 방법은 내가 코드를 실행하면C# :이 명령과 관련된 열려있는 DataReader가 이미 있습니다.

, 나는 오류를 얻을 ... IP를 대상, 고객 + 관련 주소, 네트워크를 삭제해야해야이 명령과 관련된 열린 DataReader가 이미 있습니다

첫째 폐쇄

그래서 나는

using(SqlDataReader....) 

과가 MultipleActiveResultSets=True을 추가하는 것으로, 조금 인터넷 검색 및 읽기 연결 문자열이 도움이됩니다. 내가 SQL 서버 2014을 사용하고

, 나는 .. 그 문제 야해 그래서, SQL 서버 2005에 문제가 있음을 들어

하지만 여전히 작동하지 않습니다 ...

예외는

var addressId = (int)command.ExecuteScalar(); 

연결 문자열에서 발생합니다 :

Data Source=.\\DATABASE;Initial Catalog=customer;Persist Security Info=True;MultipleActiveResultSets=True;User ID=sa;Password=xxxxxxxx! 

번호 :

public static Boolean ExecuteDeleteCutomer(string customerId) { 
    using (SqlConnection connection = new SqlConnection(new DatabaseConnection().ConnectionString)) { 
     connection.Open(); 

     SqlCommand command = connection.CreateCommand(); 
     SqlTransaction transaction; 
     SqlDataReader locationReader; 
     SqlDataReader networkReader; 
     SqlDataReader ipaddressReader; 

     // Start a local transaction to delete a customer and related table entries. 
     transaction = connection.BeginTransaction("StartTransaction DeleteCustomer"); 

     // Must assign both transaction object and connection 
     // to Command object for a pending local transaction 
     command.Connection = connection; 
     command.Transaction = transaction; 

     try { 
      //First get the locations of selected customer 
      command.Parameters.AddWithValue("@customerId", customerId); 
      command.CommandText = 
        "SELECT l_id from location where c_id = @customerId"; 
      locationReader = command.ExecuteReader(); 

      using (locationReader) { //save location ids in a reader 
       while (locationReader.Read()) { 
        var locationID = locationReader.NextResult(); 
        command.Parameters.AddWithValue("@locationId", locationID); 
        command.CommandText = 
         "SELECT a_id from address where l_location = @locationId"; 
        var addressId = (int)command.ExecuteScalar(); // get address ID to delete later 

        command.Parameters.AddWithValue("@addressId", addressId); 
        command.CommandText = "SELECT n_id from network where n_location = @locationId"; 

        using (networkReader = command.ExecuteReader()) { // save networks in a reader; 
         while (networkReader.Read()) { 
          var networkId = networkReader.NextResult(); 
          command.Parameters.AddWithValue("@networkId", networkId); 
          command.CommandText = "SELECT ip_id from ipaddress where n_id = @networkId"; 

          using (ipaddressReader = command.ExecuteReader()) { // get ipaddressId ID to delete later 
           while (ipaddressReader.Read()) { 
            var ipaddressId = ipaddressReader.NextResult(); 
            command.Parameters.AddWithValue("@ipId", ipaddressId); 
            command.CommandText = "Delete from ipaddress where ip_id = @ipId; "; 
            command.ExecuteScalar(); 
           } 
          } 

          command.CommandText = "Delete from network where n_id = @networkId; "; 
          command.ExecuteScalar(); 
         } 
        } 

        command.CommandText = "Delete from location where l_id = @locationID; "; 
        command.ExecuteScalar(); 
       } 
      } 

      command.CommandText = "Delete from customer where c_id = @customerId; "; 
      command.ExecuteScalar(); 

      // Attempt to commit the transaction. 
      transaction.Commit(); 

      return true; 
     } 
     catch (Exception ex) { 
      Console.WriteLine("Commit Exception Type: {0}", ex.GetType()); 
      Console.WriteLine(" Message: {0}", ex.Message); 

      // Attempt to roll back the transaction. 
      try { 
       transaction.Rollback(); 
      } 
      catch (Exception ex2) { 
       // This catch block will handle any errors that may have occurred 
       // on the server that would cause the rollback to fail, such as 
       // a closed connection. 
       Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType()); 
       Console.WriteLine(" Message: {0}", ex2.Message); 
      } 

      return false; 
     } 
    } 
} 

고마워요!

+2

오류 메시지는 자체적으로 설명됩니다! –

+0

이유는 무엇입니까? var locationID = locationReader.NextResult();'? 여러 SELECT 문을 사용하여 쿼리를 작성하면 독자가 다음 결과로 나아갑니다. 'while (networkReader.Read()) '루프에서 그렇게하고 싶지는 않습니다. 대신 int int를 사용할 수 있습니다. networkId = networkReader.GetInt32 (0); –

+0

명령에 대해 두 개 이상의 열린 DataReader를 사용할 수 없습니다. – Hambone

답변

1

오류 메시지가 표시 될 때 이미 DataReaderCommand 개체와 연결되어 있습니다.

실행할 각 (중첩 된) 명령에 대해 SqlCommand 개체를 새로 만들어야합니다.

SqlCommand locationCommand = connection.CreateCommand(); 
SqlCommand networkCommand = connection.CreateCommand(); 
SqlCommand ipAddrCommand = connection.CreateCommand(); 

지정하여 CommandText 그 명령 각 개체에 필요에 따라 필요에 따라 다음 각 하나에 ExecuteReader 및 프로세스를 호출 할 수 있습니다.

+0

감사합니다. 각각의 중첩 된 명령에 대해 하나의 Command를 생성했습니다 :-) –

0

outer 및 inner 명령에 대해 다른 명령 인스턴스를 사용하십시오. 그래서 본질적 :

var innerCommand = ... 
innerCommand.CommandText = "Delete from ipaddress where ip_id = @ipId; "; 
var ipId = innerCommand.Parameters.Add(...); 
while (ipaddressReader.Read()) { 
    ipId.Value = ... 
    innerCommand.ExecuteNonQuery(); 
} 

(각각의 명령과 유사)

기본적으로, 각 명령 인스턴스는 관계없이 접속을 공유 여부에 한 번에 한 번만 실행되어야한다.