2016-09-19 63 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

爲什麼你需要在這裏進行交易?如果您的更新語句是單個語句,則它失敗或通過。您期望處理多少條記錄?您可以讀取所有的ID然後運行更新循環。你能計算出服務器上的新值嗎?在這種情況下,您可以將更新作爲單個語句運行。 –

+0

Look @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

這裏的問題是您正試圖在同一時間閱讀和更新。您正在調用數據庫中的更新函數,這是不允許將數據庫保持在一致狀態的。

這是一個有點修改的代碼,其中arraylist用於存儲來自reader的數據,然後循環調用update函數。

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(); 
       } 
      } 

    } 
}