2016-09-19 8 views
0

いくつかの内部結合を持つSQL Select文があるコンソールアプリケーションがあります。この文のすべての結果に対して、 C#を使用して新しい値を返します。ここでSQL SELECT文の結果を繰り返し処理して特定のテーブルを更新する方法

私はすでに試した何:

using System; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Data; 

namespace MyProgram 
{ 
    class Program 
    { 
     private static SqlConnection _connection; 
     private static SqlTransaction _transaction; 

     static void Main(string[] args) 
     { 
      using (var connection = new SqlConnection()) 
      { 
       try 
       { 
        connection.ConnectionString = ConfigurationManager.ConnectionStrings["myConfig"].ConnectionString; 
        connection.Open(); 
        _connection = connection; 

        using (var command = connection.CreateCommand()) 
        { 
          command.CommandText = 
          "My Select sql stament with inner joins"; 

         using (var reader = command.ExecuteReader()) 
         { 
          var indexOfColumn3 = reader.GetOrdinal("IDExtObject"); 

          while (reader.Read()) 
          { 
           _transaction = _connection.BeginTransaction("UpdateTransaction"); 
           command.Transaction = _transaction; 

           var extId = reader.GetValue(indexOfColumn3).ToString(); 

           string finalId = "Something new..."; 

           try 
           { 
            UpdateIdSqlTransaction(extId, finalId); 
            _transaction.Commit(); 
           } 
           catch (Exception) 
           { 
            _transaction.Rollback(); 
           } 
          } 
         } 
        } 
       } 
       catch (Exception) 
       { 
        if (_transaction != null) 
         _transaction.Rollback(); 
       } 
       finally 
       { 
        if (connection.State == ConnectionState.Open) 
        { 
         connection.Close(); 
        } 
       } 
      } 

      Console.ReadLine(); 
     } 

     private static void UpdateIdSqlTransaction(string objectId, string newId) 
     { 
      using (_connection) 
      { 
       SqlCommand command = _connection.CreateCommand(); 
       command.Connection = _connection; 

       var commandText = "The update SQL statement..."; 
       command.CommandText = commandText; 
       command.Parameters.AddWithValue("@ID", objectId); 
       command.Parameters.AddWithValue("@newId", newId); 
       command.ExecuteNonQuery(); 
      } 
     } 
    } 
} 

問題は、私はこの例外を取得していますということです。

で実行されている他のスレッドがあるので

{ "新しいトランザクションが許可されていませんセッション」を参照してください。}}

これはどのような問題ですか?これをどのように達成できますか?

+0

この「command.Transaction = _transaction;」を入力できますか? ExecuteReader文の前に? – FakeisMe

+0

ここでトランザクションが必要なのはなぜですか? update文が単一の文である場合、その文は失敗したか、または合格したものです。処理するレコード数はいくつですか?すべてのIDを読み取り、更新ループを実行することができます。あなたはサーバー上で新しい価値を計算できますか?この場合、更新は1つのステートメントとして実行できます。 –

+0

ルック@SergeyL私はプロセスを開始したいとレコードのいずれかが失敗した場合、私はトランザクション全体をロールバックしたい。 –

答えて

2

データの読み取りに使用している既存の接続を閉じる必要があります。 DataReaderは、データの読み取り専用ストリームです。

の下に与えられたとして、それを実行します。

  • を最初にデータを読み込み、変数に格納します。 DataReaderがデータの読み取りに使用している接続を閉じます。
  • ループを使用して、トランザクションを作成して、同じトランザクションを使用してデータを更新します。
  • 更新されると、トランザクションをコミットできます。

指定された手順に従ってコードを変更してください。おかげ

Check this link for more details on SO

は、次のコードを試してみてください。私はデータベースのコードを設定していないので、私はそれを実行していないことに注意してください。それが役に立てば幸い。

using System; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Data; 
using System.Collections.Generic; 

namespace MyProgram 
{ 

    class Item 
    { 
     public string OldValue { get; set; } 
     public string NewValue { get; set; } 
    } 

    class Program 
    { 
     //private static SqlConnection _connection; 

     private static string connectionString = ConfigurationManager.ConnectionStrings["myConfig"].ConnectionString; 

     static void Main(string[] args) 
     { 
      List<Item> items = new List<Item>(); 
      ReadData(ref items); 

      UpdateIdSqlTransaction(items); 

      Console.ReadLine(); 
     } 

     private static void ReadData(ref List<Item> items) 
     { 
      using (var connection = new SqlConnection()) 
      { 
       connection.ConnectionString = connectionString; 
       connection.Open(); 
       //_connection = connection; 

       using (var command = connection.CreateCommand()) 
       { 
        command.CommandText = 
        "My Select sql stament with inner joins"; 

        using (var reader = command.ExecuteReader()) 
        { 
         var indexOfColumn3 = reader.GetOrdinal("IDExtObject"); 

         while (reader.Read()) 
         { 
          var extId = reader.GetValue(indexOfColumn3).ToString(); 
          string finalId = "Something new..."; 

          items.Add(new Item() { OldValue = extId, NewValue = finalId }); 
         } 
        } 
       } 
      } 
     } 

     private static void UpdateIdSqlTransaction(List<Item> items) 
     { 
      SqlTransaction transaction; 
      using (var connection = new SqlConnection()) 
      { 
       connection.ConnectionString = connectionString; 
       connection.Open(); 

       using (SqlCommand command = connection.CreateCommand()) 
       { 
        command.Connection = connection; 
        transaction = connection.BeginTransaction("UpdateTransaction"); 
        command.Transaction = transaction; 
        try 
        { 
         foreach (var item in items) 
         { 
          var commandText = "The update SQL statement..."; 
          command.CommandText = commandText; 
          command.Parameters.AddWithValue("@ID", item.OldValue); 
          command.Parameters.AddWithValue("@newId", item.NewValue); 
          command.ExecuteNonQuery(); 
         } 
         transaction.Commit(); 
        } 
        catch (Exception) 
        { 
         transaction.Rollback(); 
         //Log the exception here. To know, why this failed. 
        } 
       } 
      } 
     } 
    } 
} 
+0

私はこれを試してみましょう。 –

+0

申し訳ありません@vivek同じエラーが発生しました "{"セッション内で実行中の他のスレッドがあるため、新しいトランザクションは許可されません。"}" –

+0

コード例をプロビジョニングできますか? –

1

ここでの問題は、同時に読んで更新しようとしていることです。 datareader内で、更新機能を呼び出していますが、DBを一貫性のある状態に維持することはできません。

ここでは、arraylistを使用してリーダーからのデータを格納し、ループスルーから更新関数を呼び出すためのコードが変更されています。

class Program 
{ 
    private static SqlConnection _connection; 
    private static SqlTransaction _transaction; 
    private static ArrayList array; 



    static void Main(string[] args) 
    { 
      _connection = new SqlConnection(ConfigurationManager.ConnectionStrings["myConfig"].ConnectionString); 

      try 
      { 

       using (_connection) 
       { 

        string finalId = "Something new..."; 
        var command = _connection.CreateCommand(); 
        command.CommandText = "your query"; 
        _connection.Open(); 

        array = new ArrayList(); 

        using (var reader = command.ExecuteReader()) 
        { 
         var indexOfColumn3 = reader.GetOrdinal("IDExtObject"); 

         while (reader.Read()) 
         { 

          var extId = reader.GetValue(indexOfColumn3).ToString(); 


          array.Add(extId); 


         } 
        } 

        foreach (string id in array) 
        { 


         UpdateIdSqlTransaction(id, finalId); 

        } 

       } 
      } 

      catch (Exception) 
      { 

      } 
      finally 
      { 
       if (_connection.State == ConnectionState.Open) 
       { 
        _connection.Close(); 
       } 
      } 



     Console.ReadLine(); 
    } 

    private static void UpdateIdSqlTransaction(string objectId, string newId) 
    { 
     try 
      { 

       if (_connection.State == ConnectionState.Closed) 
       { 
        _connection.Open(); 
       } 
      SqlCommand command = _connection.CreateCommand(); 
      command.Connection = _connection; 

      _transaction = _connection.BeginTransaction("UpdateTransaction"); 
      command.Transaction = _transaction; 

      var commandText = "your update statement"; 
      command.CommandText = commandText; 
      command.Parameters.AddWithValue("@ID", objectId); 
      command.Parameters.AddWithValue("@newId", newId); 
      command.ExecuteNonQuery(); 

      _transaction.Commit(); 
     } 
     catch (Exception) 
         { 
          _transaction.Rollback(); 
         } 
      finally 
      { 
       if (_connection.State == ConnectionState.Open) 
       { 
        _connection.Close(); 
       } 
      } 

    } 
} 
関連する問題