7

TADOQuery、TADOCommand、または TADODataSet でのクエリ実行タイムアウトの設定に問題があります (それぞれで試しました)。データベースに接続し、結果としてデータセットを返すストアド プロシージャを定期的に実行する小さなアプリケーションがあります。私の目的は、このアプリケーションを常にオンラインに保つことですが、私の問題は、接続が失われると、(前述のコンポーネントの 1 つを介して) 実行されたばかりのコマンドのタイムアウトにデフォルトの 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、それは機能しません。代わりにのを使用する必要がCommandTimeoutありTADODataSetます。

サーバーが利用できない場合、質問には「接続が失われました」と表示されます。コンポーネントを指定ConnectionTimeoutする必要があります。TADOConnectionデフォルトは、制御がアプリケーションに返される15秒前です。

編集1CommandTimeoutが機能しない状況を発見したと思います。私はこれを本当に大きなテーブルに対してテストしました。すべての行を返すには数分かかります。ストアドプロシージャが実行する場合select * from BigTable、クエリタイムアウトは発生しません。少なくとも私はそれを待つのに十分な忍耐力がありませんでした。ただし、クエリがこのようselect * from BigTable order by Col1になり、にインデックスがないCol1場合、CommandTimoutは期待どおりに機能します。

2つのクエリの違いは、SSMSで実行すると明らかです。1つ目はすぐに行を返し始め、2つ目は行を返す前にそれについて「考える」必要があります。SQL Serverが必要な行を見つけて返し始めると、CommandTimeoutは機能しません。

に設定CursorLocationするとclUseServerCommandTimeout両方のクエリで期待どおりに機能します。

于 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 秒間実行されます
  • 1 秒後に 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 に答える