2017-01-31 37 views
0

現在、複数のSqlDataReaderと1つの方法でコマンドに問題があります。この方法は、私は、コードを実行すると、私はエラーC#:既にこのコマンドに関連付けられている開いているDataReaderがあります

を取得しなければなりません。このコマンドに関連付けられているオープンのDataReaderが既にあります...

を顧客+その関連アドレス、ネットワーク、するIPアドレスを削除する必要がありますだから私は少しグーグルと読み、

using(SqlDataReader....) 

とにMultipleActiveResultSets=Trueを追加することを第一

を閉じました接続文字列が役立つはずです。私は、SQL Server 2014を使用してい

は、私が...それが問題になるはずのよう、SQL Server 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 networkId = networkReader.GetInt32(0); 'を使用します。 –

+0

コマンドに対して複数のDataReaderを開くことはできません。 – Hambone

答えて

1

エラーメッセージが表示されるので、すでにDataReaderがそのCommandオブジェクトに関連付けられています。

実行する各(入れ子になった)コマンドに対して新しいSqlCommandオブジェクトを作成する必要があります。

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

これらのコマンドは、オブジェクトのそれぞれに、必要に応じてごCommandTextを割り当て、必要に応じて、あなたはそれぞれ1およびプロセスにExecuteReaderを呼び出すことができます。

+0

ありがとうございました!私は入れ子になったコマンドごとに一つのCommandを作成しました:-) –

0

外部コマンドと内部コマンドに異なるコマンドインスタンスを使用します。したがって、本質的に:

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

(各コマンドについて類似)

は基本的に、各コマンドのインスタンスのみに関係なく接続を共有するか否かに、時間に一度実行されるべきです。

関連する問題

 関連する問題