1

あるサーバーから別のサーバーにデータをコピーするための次のコードがあります。

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

いずれかのテーブルのスキーマを変更して強制的にエラーを発生させた場合、変更をロールバックしようとすると、「This SqlTransaction has completed」というエラーが表示されます。この問題を修正するにはどうすればよいですか? また、なぜこの問題が発生するのですか?

4

1 に答える 1

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
    }
}
于 2013-10-17T18:54:01.133 に答える