简体   繁体   中英

How to iterate through SQL select statement results and update a specific table

There is a console app where I have a sql select statement with some inner joins.I want for every result of this statement to update a column of one of these tables with a new value using C#.

Here what I've already tried:

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

The problem is that I am getting this exception:

{"New transaction is not allowed because there are other threads running in the session."}

What is the problem and how can I achieve this?

You need to close the existing connection that you are using to Read the data. DataReader is a read only stream of data.

Do it as given below:

  • First read the data and store it in a variable. Close the connection that DataReader is using to read the data.
  • Now use the loop and create a transaction to update the data using the same transaction.
  • Once updated, you can commit the transaction.

Change your code as per the instructions given. Thanks

Check this link for more details on SO

Try the following code. Note that I have not run it as I do not have database set up for the code. Hope it helps.

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.
                    }
                }
            }
        }
    }
}

The issue here is you are trying to read and update at the same time. Within the datareader you are calling update function which is not allowed to maintain the DB in a consistent state.

Here is a bit modified code, where arraylist is used to store data from reader and then loop through to call update function.

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

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM