如何遍历SQL select语句结果并更新特定表

时间:2016-09-19 10:44:38

标签: c# sql sql-server

有一个控制台应用程序,我有一个带有一些内部联接的sql select语句。我希望此语句的每个结果都使用C#用新值更新其中一个表的列。

这是我已经尝试过的:

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

问题是我得到了这个例外:

  

{"不允许新事务,因为会话中还有其他线程运行。"}

问题是什么?如何实现?

2 个答案:

答案 0 :(得分: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.
                    }
                }
            }
        }
    }
}

答案 1 :(得分: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();
                }
            }

    }
}