删除事务期间ZombieCheck中的InvalidOperationExceptionSystem

时间:2018-01-04 14:18:53

标签: c# sql

我正在尝试清除Azure数据库中的日志,这是我得到的异常,它似乎只发生在Azure环境中。

InvalidOperationException: This SqlTransaction has completed; it is no longer usable.
  Module "System.Data.SqlClient.SqlTransaction", line 16, col 0, in ZombieCheck
    Void ZombieCheck()
  Module "System.Data.SqlClient.SqlTransaction", line 53, col 0, in Rollback
    Void Rollback()
  File "D:\BuildAgent5\work\148e47915efc80eb\Janitor.cs", line 108, col 29, in ExecuteDatabaseTransaction
    Void ExecuteDatabaseTransaction(Microsoft.Extensions.Configuration.IConfiguration, System.String)
  File "D:\BuildAgent5\work\148e47915efc80eb\Startup.cs", line 37, col 17, in .ctor
    Void .ctor()

执行此代码后出现此错误:

ExecuteDatabaseTransaction(configuration,
     "DELETE profiling.MiniProfilerTimings "
     + "FROM profiling.MiniProfilerTimings "
     + "WHERE EXISTS(SELECT * FROM profiling.MiniProfilers "
     + "WHERE profiling.MiniProfilers.Id = MiniProfilerId "
     + "AND profiling.MiniProfilers.Started < GETDATE() - " 
     + configuration.GetSection("ProfilingData")["DaysToKeep"] + ")");

此连接2表用于获取创建Profiler时的日期,如果日期在DaysToKeep下,则删除它似乎在小表上正常工作,并且当处理的数据不多时。如果行数很大,它每次都会失败。我不确定为什么会发生这种情况,但我认为这与我的交易没有正确创建和提交有关。

这是交易方法:

  private static void ExecuteDatabaseTransaction(IConfiguration configuration, string commandText)
    {
        using (var connection = new SqlConnection(configuration.GetSection("ConnectionStrings")["SignupDatabase"]))
        {
            connection.Open();

            using (var transaction = connection.BeginTransaction())
            {
                try
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.Transaction = transaction;
                        command.CommandText = commandText;
                        var rowsDeleted = command.ExecuteNonQuery();
                        Console.WriteLine("Rows Affected: " + rowsDeleted);
                    }

                    Console.WriteLine("Records are deleted from database.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
                    Console.WriteLine("  Message: {0}", ex.Message);

                    try
                    {
                        transaction.Rollback();
                    }
                    catch (Exception ex2)
                    {
                        Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                        Console.WriteLine("  Message: {0}", ex2.Message);
                        throw;
                    }
                    throw;
                }
                transaction.Commit();
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

原来这是因为一个非常庞大的数据库需要大量的连接和删除总体上需要很长时间才能完成。

如果添加CommandTimout = 0,它将不会超时,但要注意无限超时不是最佳解决方案。

  int rowsAffected;
  connection.Open();
  var command = connection.CreateCommand();
  var transaction = connection.BeginTransaction();

  command.Connection = connection;
  command.CommandTimeout = 0;
  command.Transaction = transaction;