我在带有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没有超时?
答案 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
}