当执行SQL代码优化数据库时,Hangfire会导致超时过期异常-ASP.NET Core

时间:2019-01-20 05:45:57

标签: asp.net sql-server asp.net-core hangfire

我将以下代码设置为预定任务:

public class OptimizeDatabase : IJob {

    #region Constructor
    public OptimizeDatabase(DataContext dataContext) {
        DbContext = dataContext;
    }
    #endregion

    #region Fields
    private readonly DataContext DbContext;
    #endregion

    #region Methods
    public async Task Execute() {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        string result = "Ok";
        try {
            // Rebuild Indexes
            DbContext.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable \"ALTER INDEX ALL ON ? REBUILD WITH (ONLINE=OFF)\"");
            // Update Statistics
            DbContext.Database.ExecuteSqlCommand("EXEC sp_updatestats;");
        }
        catch (Exception ex) {
            result = ex.Message + Environment.NewLine + ex.StackTrace;
        }
        stopWatch.Stop();
        DbContext.TaskLogs.Add(new TaskLog {
            Date = DateTime.Now,
            ElapsedSeconds = stopWatch.Elapsed.TotalSeconds,
            Result = result,
            Task = "Optimize Database"
        });
        await DbContext.SaveChangesAsync();
    }
    #endregion
}

它已配置为在Startup.cs中运行

RecurringJob.AddOrUpdate<OptimizeDatabase>(x => x.Execute(), Cron.Daily(10));

所有其他计划任务执行都没有问题,但是,该任务总是引发以下错误:

  

超时已过期。在完成之前,超时时间已过   操作或服务器无响应。在   System.Data.SqlClient.SqlConnection.OnError(SqlException异常,   布尔值breakConnection,动作为1 wrapCloseInAction)

任何想法或见解都会受到赞赏。

1 个答案:

答案 0 :(得分:0)

超时问题是因为其中一个查询花费的时间更长。

据我所知,.Net中有2个超时,即连接超时(ConnectionTimeout Property)和命令超时(CommandTimeout Property)。这两个超时的默认时间均为30秒。

我建议您:

  • 在SQL Management Studio中运行查询,以了解代码显示顺序运行两个查询所需的时间。
  • 在上一次在SQL Management Studio中运行的时间(秒)内设置连接超时和命令超时。如果超时继续出现,请尝试向每个超时添加更多时间,向每个超时添加30秒,直到找到执行查询所需的最短时间为止。找到它后,请确保每次超时都额外增加30秒。

使用部分代码,所做的更改将类似于:

try {
        // Change CommandTimeout
        DbContext.Database.CommandTimeout = 120;
        // Rebuild Indexes
        DbContext.Database.ExecuteSqlCommand("EXEC sp_MSforeachtable \"ALTER INDEX ALL ON ? REBUILD WITH (ONLINE=OFF)\"");
        // Update Statistics
        DbContext.Database.ExecuteSqlCommand("EXEC sp_updatestats;");
    }
    catch (Exception ex) {
        result = ex.Message + Environment.NewLine + ex.StackTrace;
    }

您可以看一下这篇文章,它解释了一个可能的超时原因https://stackoverflow.com/a/8603111/2654879的好方案。

我希望这个答案可以帮助您解决这个问题。

此致

JB