2016-09-19 44 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(); 
       } 
      } 

    } 
}