有一个控制台应用程序,我有一个带有一些内部联接的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();
}
}
}
}
问题是我得到了这个例外:
{"不允许新事务,因为会话中还有其他线程运行。"}
问题是什么?如何实现?
答案 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();
}
}
}
}