我有以下代码将数据从一台服务器复制到另一台服务器:
private static string CopyData(string sourceConnection, string targetConnection, bool push = true)
{
string result = "Copy started";
SqlConnection source = new SqlConnection(sourceConnection);
SqlConnection target = new SqlConnection(targetConnection);
SqlTransaction targetTransaction;
source.Open();
target.Open();
if (source.State != ConnectionState.Open || target.State != ConnectionState.Open)
{
throw new Exception("Unable to connect to server at this time.");
}
targetTransaction = target.BeginTransaction();
try
{
ClearTable(target, targetTransaction, "TableAAA");
ClearTable(target, targetTransaction, "TableBBB");
CopyTable(source, target, targetTransaction, "TableAAA");
CopyTable(source, target, targetTransaction, "TableBBB");
targetTransaction.Commit();
result = "Copy successful";
}
catch (Exception E)
{
targetTransaction.Rollback();
result = "An SQL Error has occurred. Unable to copy data at this time.\n\n" + E.Message;
}
finally
{
target.Close();
source.Close();
}
return result;
}
private static void ClearTable(SqlConnection destination, SqlTransaction tran, string table)
{
SqlCommand cmd = new SqlCommand(string.Format("DELETE FROM {0}", table), destination);
cmd.Transaction = tran;
cmd.ExecuteNonQuery();
}
private static void CopyTable(SqlConnection source, SqlConnection destination, SqlTransaction tran, string table)
{
SqlCommand cmd = new SqlCommand(string.Format("DELETE FROM {0}", table), destination);
cmd.Transaction = tran;
cmd.ExecuteNonQuery();
cmd = new SqlCommand(string.Format("SELECT * FROM {0}", table), source);
SqlDataReader reader = cmd.ExecuteReader();
SqlBulkCopy bulkData = new SqlBulkCopy(destination, SqlBulkCopyOptions.Default, tran);
bulkData.DestinationTableName = table;
bulkData.BulkCopyTimeout = (int)Properties.Settings.Default.CommandTimeOut;
bulkData.WriteToServer(reader);
bulkData.Close();
reader.Close();
}
如果我通过更改其中一个表的架构来强制执行错误,则在尝试回滚任何更改时会收到错误“此SqlTransaction已完成”。我该如何纠正这个问题以及为什么会这样?
答案 0 :(得分:2)
我不确定您遇到的确切问题,但我建议您以使用using
语句的方式重写代码。这样可以防止您显式关闭连接或回滚事务。
private static string CopyData(string sourceConnection, string targetConnection, bool push = true)
{
using (var source = new SqlConnection(sourceConnection))
using (var target = new SqlConnection(targetConnection))
{
source.Open();
target.Open();
// no need to check for open status, as Open will throw an exception if it fails
using (var transaction = target.BeginTransaction())
{
// do work
// no need to rollback if exception occurs
transaction.Commit();
}
// no need to close connections explicitly
}
}