最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

sql server - FireDAC timeout seems to be ignored - Stack Overflow

programmeradmin3浏览0评论

I want to limit the time that my queries take to retrieve their data, this is supposed to be done through the ResourceOptions.CmdExecTimeout property, that controls Execute & Open commands.

But when I try it, it gets ignored and my query remains unresponsive instead of triggering an exception. See this example:

procedure TfrmMainForm.btnSynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := '''
     DECLARE @X int
     WHILE 1=1   -- Infinite Loop
       SET @X = 1
     ''';
    
  Query.ResourceOptions.CmdExecTimeout := 1000;
  try
    Query.Open;
    ShowMessage('Query Opened');
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

The SQL is an infinite loop and I expect the Query.Open to trigger an exception after the 1000ms timeout, but nothing happens.

The cnConnection connects to a SQL Server through the Microsoft ODBC Driver 17 for SQL Server.

  object cnConnection: TFDConnection
    Params.Strings = (
      'Database=agilITy_0002'
      'Server=10.0.0.48'
      'OSAuthent=Yes'
      'MARS=yes'
      'ODBCAdvanced=TrustServerCertificate=Yes'
      'DriverID=MSSQL')
    Connected = True
    LoginPrompt = False
    Left = 60
    Top = 152
  end

I've also tried to open that query asynchronously, but again no exception is triggered, nothing happens.

procedure TfrmMainForm.QueryOpened(Dataset: TDataset);
begin
  ShowMessage('Query Opened');
end;
    
procedure TfrmMainForm.btnAynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := '''
    DECLARE @X int
    WHILE 1=1   -- Infinite Loop
      SET @X = 1
    ''';
    
  Query.ResourceOptions.CmdExecMode := amAsync;
  Query.ResourceOptions.CmdExecTimeout := 1000;
  Query.AfterOpen := QueryOpened;
  try
    Query.Open;
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

Do you see what I'm doing wrong? How can I set a timeout for the opening of my queries?

I want to limit the time that my queries take to retrieve their data, this is supposed to be done through the ResourceOptions.CmdExecTimeout property, that controls Execute & Open commands.

But when I try it, it gets ignored and my query remains unresponsive instead of triggering an exception. See this example:

procedure TfrmMainForm.btnSynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := '''
     DECLARE @X int
     WHILE 1=1   -- Infinite Loop
       SET @X = 1
     ''';
    
  Query.ResourceOptions.CmdExecTimeout := 1000;
  try
    Query.Open;
    ShowMessage('Query Opened');
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

The SQL is an infinite loop and I expect the Query.Open to trigger an exception after the 1000ms timeout, but nothing happens.

The cnConnection connects to a SQL Server through the Microsoft ODBC Driver 17 for SQL Server.

  object cnConnection: TFDConnection
    Params.Strings = (
      'Database=agilITy_0002'
      'Server=10.0.0.48'
      'OSAuthent=Yes'
      'MARS=yes'
      'ODBCAdvanced=TrustServerCertificate=Yes'
      'DriverID=MSSQL')
    Connected = True
    LoginPrompt = False
    Left = 60
    Top = 152
  end

I've also tried to open that query asynchronously, but again no exception is triggered, nothing happens.

procedure TfrmMainForm.QueryOpened(Dataset: TDataset);
begin
  ShowMessage('Query Opened');
end;
    
procedure TfrmMainForm.btnAynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := '''
    DECLARE @X int
    WHILE 1=1   -- Infinite Loop
      SET @X = 1
    ''';
    
  Query.ResourceOptions.CmdExecMode := amAsync;
  Query.ResourceOptions.CmdExecTimeout := 1000;
  Query.AfterOpen := QueryOpened;
  try
    Query.Open;
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

Do you see what I'm doing wrong? How can I set a timeout for the opening of my queries?

Share Improve this question edited Mar 31 at 19:22 Remy Lebeau 600k36 gold badges507 silver badges851 bronze badges asked Mar 31 at 11:38 Marc GuillotMarc Guillot 6,4951 gold badge20 silver badges52 bronze badges 1
  • 1 I suspect that Query.Open is not one of the documented situations where the timeout is implemented. As TFDQuery is derived from TDataSet, then only fetching data will be covered. I would step through the sources of FireDac to see where it hangs, is it in the opening stage or during fetching. – mjn Commented Mar 31 at 17:12
Add a comment  | 

1 Answer 1

Reset to default 2

The problem was my query. Once I changed that simple test loop for a real SELECT statement then the timeout property already worked as expected.

发布评论

评论列表(0)

  1. 暂无评论