7

我在使用 TADOQuery、TADOCommand 或 TADODataSet 设置查询执行超时时遇到问题(我都试过了)。我有一个很小的应用程序,它连接到数据库并定期执行存储过程,结果返回数据集。我的目标是让这个应用程序始终在线,但我的问题是,当连接丢失时,刚刚执行的命令(通过上述组件之一)的超时时间默认为 30 秒。我一直在寻找解决方案,但没有任何效果。 您能否给我一个建议,如何将 CommandTimeout 例如设置为 5 秒或更好地说明如何修改 ADODB.pas 以尊重我自己的超时,好吗?

对此有很多“解决方案”,例如 set DataComponent.Connection.CommandTimeout := 1; 但实际上,没有任何效果。我正在使用 D2009、MSSQL2005 和数据组件的连接是在线程中动态创建的。

最后,我试过的是这个

// protected variable owned and created in the thread with its own connection
var Query_Object: TADODataSet; 

// connection timeout is set to 3 seconds
Query_Object.Connection.ConnectionTimeout := 3;
...

// this piece of code I'm calling periodically in the only one existing thread
...
SQL_Query := 'EXEC my_procedure_which_returns_dataset'

with Query_Object do
  begin
    Close;    
    CommandType := cmdText;
    CommandText := SQL_Query;
    CommandTimeout := 5;             // doesn't affect the timeout
    CursorLocation := clUseServer;   // let the dataset retreives prepared data
    Open;
  end;

// and here I need to get faster than in the default 15 seconds to let the user
// know that the reading takes more than mentioned 5 seconds
...

非常感谢 :)

4

3 回答 3

5

CommandTimeout当您有长时间运行的查询时,它会启动。有一个CommandTimeout属性,TADOConnection但这不起作用。您必须改用CommandTimeoutof TADODataSet

如果服务器不可用,您的问题是“连接丢失”,您需要指定ConnectionTimeout组件TADOConnection。默认值为 15 秒,然后控制权返回给您的应用程序。

编辑 1我想我发现了 CommandTimeout 不起作用的情况。我已经在一张非常大的桌子上对此进行了测试。返回所有行需要几分钟。如果我的存储过程确实select * from BigTable查询超时永远不会发生。至少我没有足够的耐心等待它结束。但是,如果查询看起来像这样select * from BigTable order by Col1并且没有索引Col1,则 CommandTimout 会按预期工作。

在 SSMS 中运行这两个查询时,它们之间的区别很明显。第一个开始立即返回行,第二个需要在返回行之前“考虑”它。当 SQL Server 找到它需要的行并开始返回它们时,CommandTimeout 不起作用。

如果您设置CursorLocationclUseServerCommandTimeout这两个查询都将按预期工作。

于 2011-02-22T22:29:06.047 回答
1

以下是我们为长期运行的报告设置超时时间为 300 的方法。

  //***** Fix setting CommandTimeOut. 
  //      CommandTimeOut "should" get the timeout value from its connection. 
  //      This is not supported in ADODB (using Delphi5)
  TADODataSet(qryReport).CommandTimeout := ADOConnection.CommandTimeout;

编辑

在我的开发机器上执行以下代码在 1 秒后超时。

  • 该查询有一个连接到我们的 SQLServer 生产数据库的字符串。
  • 脚本(尝试)运行 10 秒
  • 一秒钟后,我得到一个 TimeOut 异常

测试

procedure TForm1.btn1Click(Sender: TObject);
const
  SSQL: string =
    'DECLARE    @intLoop int '#13#10
    + 'SET @intLoop = 10 '#13#10
    + 'WHILE @intLoop > 1 '#13#10
    + 'BEGIN '#13#10
    + ' SELECT  @intLoop, GetDate() '#13#10
    + ' WAITFOR DELAY ''00:00:01'' '#13#10
    + ' SELECT  @intLoop = @intLoop -1 '#13#10
    + 'END ';
begin
  qry1.SQL.Text := SSQL;
  TADODataSet(qry1).CommandTimeout := 1;
  qry1.ExecSQL;
end;
于 2011-02-22T10:59:34.037 回答
0

我一直使用以下代码在 TADOQuery 上设置 CommandTimeout 值。如果您调整类名,它也应该与其他类一起使用。

type 
TADOQueryHack = class(TADOQuery);

...

TADOQueryHack(Qry).CommandTimeout := COMM_TIMEOUT;
于 2011-02-22T11:51:32.033 回答