ADO组件CommandTimeout

时间:2011-02-22 10:41:40

标签: delphi timeout ado tadoquery tadodataset

我遇到了使用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
...

非常感谢:)

3 个答案:

答案 0 :(得分:5)

当你长时间运行查询时,

CommandTimeout正在开始。 CommandTimeout属性为TADOConnection,但不起作用。您必须使用CommandTimeout的{​​{1}}代替。

如果服务器不可用,您的问题显示“连接丢失”,则需要指定TADODataSet组件的ConnectionTimeout。在将控制权返回给您的应用程序之前,默认值为15秒。

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

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

如果您将Col1设置为CursorLocation,则clUseServer将按预期为两个查询工作。

答案 1 :(得分: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;

答案 2 :(得分:0)

我总是使用以下代码在TADOQuery上设置CommandTimeout值。如果您调整班级名称,它也应该与其他人一起工作。

type 
TADOQueryHack = class(TADOQuery);

...

TADOQueryHack(Qry).CommandTimeout := COMM_TIMEOUT;