SqlDataAdapter填充不超时

时间:2015-03-10 16:16:31

标签: c# ado.net

我在带有Sql Server的数据集上运行Fill操作,我正在运行一个需要几分钟才能运行的长存储过程。我希望得到一个" Timeout过期"异常,因为我将CommandTimeout设置为60秒。

IDbCommand command = defaultConnection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "Whatever";
command.CommandTimeout = 60;

SqlCommand sqlCommand = (SqlCommand)command;
Logging.Log(SeverityTypeEnum.Diagnostic, "CommandTimeout = {0}", sqlCommand.CommandTimeout);
using (SqlDataAdapter adapter = new SqlDataAdapter(sqlCommand))
{
    Logging.Log(SeverityTypeEnum.Diagnostic, "CommandTimeout = {0} {1} ", adapter.SelectCommand.CommandTimeout, adapter.SelectCommand.Connection.ConnectionTimeout);
    adapter.Fill(dataSet, "MyDataSet");
}

上面的代码只是继续运行,没有异常发生。我打印出CommandTimeout,两个地方都是60。我还打印了5的ConnectionTimeout,虽然我不认为这是相关的。代码中引用的defaultConnection只是SqlConnection的包装器。

我使用与SqlDataReader类似的过程。为什么我的Fill没有超时?

1 个答案:

答案 0 :(得分:0)

问题是Fill是两阶段操作。第一个是执行查询,第二个是获取数据。 CommandTimeout仅在第一个执行部分期间工作。

答案是不使用CommandTimeout而是使用BackgroundWorker异步运行查询。然后,您可以实现自己的超时,从而中止该线​​程。

    private static readonly BackgroundWorker Worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
    private static readonly AutoResetEvent ResetEvent = new AutoResetEvent(false);
    private static bool success;

    private static void Main()
    {
        Worker.DoWork += worker_DoWork;
        Worker.RunWorkerCompleted += WorkerRunWorkerCompleted;

        var timer = new System.Timers.Timer(60000);
        timer.Elapsed += TimerElapsed;
        timer.Enabled = true;

        Worker.RunWorkerAsync();
        ResetEvent.WaitOne();
        Logging.Log(SeverityTypeEnum.Information, (success)? "Mission succsessful" : "We have a problem Houston");
    }

    static void WorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Logging.Log(SeverityTypeEnum.Information, "Thankyou and goodnight");
        success = true;
    }

    static void TimerElapsed(object sender, ElapsedEventArgs e)
    {
        Logging.Log(SeverityTypeEnum.Information, "Time please Gentlemen, time!");
        ResetEvent.Set();  // aborts worker
    }

    private static void WorkerDoWork(object sender, DoWorkEventArgs e)
    {
        // create SqlCommand, SqlDataAdapter and call Fill as before
    }