[英]ADO components CommandTimeout
I have a problem with settings of the query execution timeout with TADOQuery, TADOCommand or TADODataSet (I've tried it with each one). 我在使用TADOQuery,TADOCommand或TADODataSet设置查询执行超时时遇到了问题(我已经尝试过每一个)。 I have a tiny application, which connects to the database and periodically executes stored procedures, which returns dataset as a result .
我有一个微型应用程序,该应用程序连接到数据库并定期执行存储过程,该过程将结果返回数据集 。 My aim is to keep this application always online, but my problem is that when the connection is lost, the timeout of just executed command (through the one of the mentioned components) takes the default 30 seconds.
我的目的是使该应用程序始终保持联机状态,但是我的问题是,当连接断开时,刚执行的命令(通过上述组件之一)的超时将默认为30秒。 I've been looking for the solution, but nothing works.
我一直在寻找解决方案,但是没有任何效果。 Could you give me an advice, how to set the CommandTimeout eg to 5 seconds or better to say how to modify ADODB.pas for respecting my own timeout, please ?
您能否给我一个建议,如何将CommandTimeout设置为5秒或更佳,比如说如何修改ADODB.pas以尊重我自己的超时时间?
There were many "solutions" for this, like set DataComponent.Connection.CommandTimeout := 1; 有很多“解决方案”,例如set DataComponent.Connection.CommandTimeout:= 1; but really, nothing works.
但实际上,没有任何效果。 I'm using D2009, MSSQL2005 and the connection along with the data component is created dynamically in the thread.
我正在使用D2009,MSSQL2005,并且连接和数据组件是在线程中动态创建的。
The last, what I've tried is this 最后,我尝试过的是
// 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
...
Thanks a lot :) 非常感谢 :)
CommandTimeout
is kicking in when you have long running queries. 当您长时间运行查询时,
CommandTimeout
会启动。 There is a CommandTimeout
property of TADOConnection
but that does not work. 没有
TADOConnection
的CommandTimeout
属性,但是不起作用。 You have to use the CommandTimeout
of the TADODataSet
instead. 您必须改为使用
TADODataSet
的CommandTimeout
。
If the server is unavailable, your question says "connection is lost", you need to specify ConnectionTimeout
of the TADOConnection
component. 如果服务器不可用,您的问题是“连接丢失”,则需要指定
TADOConnection
组件的ConnectionTimeout
。 Default is 15 seconds before control is returned to your application. 默认值为将控制权返回到应用程序之前的15秒。
Edit 1 I think I have discovered a situation where CommandTimeout does not work. 编辑1我想我已经发现CommandTimeout不起作用的情况。 I have tested this against a really big table.
我已经在一个很大的桌子上测试了这个。 It takes several minutes to return all rows.
返回所有行需要几分钟。 If my stored procedure does
select * from BigTable
the query timeout never happens. 如果我的存储过程确实
select * from BigTable
中select * from BigTable
则查询超时将永远不会发生。 At least I was not patient enough to wait it out. 至少我没有耐心等待它。 But if the query looks like this
select * from BigTable order by Col1
and there is no index on Col1
, the CommandTimout works as expected. 但是,如果查询看起来像这样
select * from BigTable order by Col1
并且对没有索引Col1
,按预期工作的CommandTimout。
The difference between the two queries is obvious when running them in SSMS. 在SSMS中运行它们时,两个查询之间的区别显而易见。 The first starts to immediately return rows and the second needs to "think" about it before it returns rows.
第一个开始立即返回行,第二个需要在返回行之前对其进行“思考”。 When SQL Server have found the rows it needs and start to return them, CommandTimeout does not work.
当SQL Server找到所需的行并开始返回它们时,CommandTimeout将不起作用。
If you set CursorLocation
to clUseServer
the CommandTimeout
will work as expected for both queries. 如果将
CursorLocation
设置为clUseServer
则CommandTimeout
将对两个查询都按预期工作。
Following is what we use to set the timeout to 300 for our long running reports. 以下是我们将长时间运行的报告的超时设置为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;
Edit 编辑
Executing following piece of code on my Development Machine times out after 1 second. 在我的开发机上执行以下代码段1秒后超时。
Test 测试
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;
I've always used the following code to set the CommandTimeout value on a TADOQuery. 我一直使用以下代码在TADOQuery上设置CommandTimeout值。 If you adjust the class name it should also work with the others as well.
如果您调整类别名称,它也应该与其他名称一起使用。
type
TADOQueryHack = class(TADOQuery);
...
TADOQueryHack(Qry).CommandTimeout := COMM_TIMEOUT;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.