【问题标题】:ADOConnection ADOQuery CommandTimeout , Override Order ( if at all )ADOConnection ADOQuery CommandTimeout,覆盖顺序(如果有的话)
【发布时间】:2021-10-27 06:02:25
【问题描述】:

这里是 Delphi 10.4.2 。一个 ADOConnection 和一个 ADOQuery 。

ADOConnection 使用 OleDB (UDL) 连接到 MSSQL。我已经离开了 CommandTimeout 30 。 现在我将 ADOQuery 放在此表单上,将其 Connection 属性设置为 ADOConnection 。所有其他值都是默认值,CommandTimeout 是 30。

现在让我们假设我们有一个非常大的表超时。使用默认的 30 秒。

我的问题是:

如果我将 ADOQuery CommandTimeout 设置为 600 它可以工作 但如果我只将 ADOConnection CommandTimeout 设置为 600,它仍然会超时

如果 ADOConnection 上的 CommandTimeout 不简单地将其值传播到它的关联组件(当然直到我覆盖它们),它有什么目的?

谢谢。

编辑 1:

ADOConnection CommandTimeout 是否实际上用于 ADOConnection 必须执行的一些后台任务来建立连接? 例如,如果我在 IDE 中激活它,然后有一个 ADOStoredProcedure 并且我想列出它使用此超时的服务器上的所有可用存储过程?

【问题讨论】:

  • 没有太多数据库经验,我只评论:TADOConnection 有一个属性ConnectionTimeout 可以在连接时间过长时停止。此外,它可以在其Commands 属性中包含命令,并为这些命令提供CommandTimeout 属性。相反,如果您使用 TADOCommand 实例作为命令,它们有自己的 CommandTimeout 属性。与ADOQuery 查询相同,它们有自己的CommandTimeout 属性。这不是很合乎逻辑吗?
  • 你编程喜欢你写的吗?标点前面有空格?喜欢Query .CommandTimeout :=30 ;?我真的很感兴趣人们为什么要使用这些额外的空间,因为我找不到任何合乎逻辑的理由。
  • @AmigoJack :没有冒犯,但你看到的东西不存在 :) 。 ADOQuery CommandTimeout 没有。中间,我就是这么写的。就像我会写的一样,例如宝马 F20。
  • @AmigoJack :我通常做 ADOQuery.CommandTimeout_:=_true; (_ = 空格)
  • 根据 MS 他们不应该干涉:docs.microsoft.com/en-us/sql/ado/reference/ado-api/…

标签: delphi ado


【解决方案1】:

根据Microsoft,每个ADO对象都尊重自己的CommandTimeout

Connection 对象上的 CommandTimeout 设置对 同一 Connection 上的 Command 对象上的 CommandTimeout 设置; 也就是说,Command 对象的 CommandTimeout 属性不继承 Connection 对象的 CommandTimeout 值的值。

我做了一个小的 MRE(使用 Delphi 10.3)来证明这一点:

program SO69733529;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  ActiveX,
  AdoDb,
  System.SysUtils;

procedure TestADOCommandTimeout;

var
  Conn : TADOConnection;
  Qry  : TADOQuery;
  SQLDelay : Integer;

begin
 Conn := TADOConnection.Create(nil);
 Qry := TADOQuery.Create(nil);
 try
  Conn.LoginPrompt := False;
  Conn.ConnectionString := 'Provider=SQLOLEDB.1;Data Source=localhost\sqlexpress;Initial Catalog=TestCustomer;Integrated Security = SSPI;';
  Conn.Connected := True;
  Qry.Connection := Conn;
  Writeln('Connected to DB');
  SQLDelay := 10;
  Conn.CommandTimeout := 5;
  try
   Writeln(Format('Waiting for %d seconds, connection timeout is %d seconds', [SQLDelay, Conn.CommandTimeout]));
   Conn.Execute(Format('WAITFOR DELAY ''00:00:%.2d''', [SQLDelay]));
   Writeln('No Timeout');
  except
   on E: Exception do
    Writeln(E.ClassName, ': ', E.Message);
  end;
  Qry.CommandTimeout := 30;
  try
   Writeln(Format('Waiting for %d seconds, query timeout is %d seconds, connection timeout is %d seconds', [SQLDelay, Qry.CommandTimeout, Conn.CommandTimeout]));
   Qry.SQL.Text := Format('WAITFOR DELAY ''00:00:%.2d''', [SQLDelay]);
   Qry.ExecSQL;
   Writeln('No Timeout');
  except
   on E: Exception do
    Writeln(E.ClassName, ': ', E.Message);
  end;
  // now redo the same test but with connection commandtimeout same as qry timeout
  Qry.CommandTimeout := 15;
  Conn.CommandTimeout := Qry.CommandTimeout;
  try
   Writeln(Format('Waiting for %d seconds, query timeout is %d seconds, connection timeout is %d seconds', [SQLDelay, Qry.CommandTimeout, Conn.CommandTimeout]));
   Qry.SQL.Text := Format('WAITFOR DELAY ''00:00:%.2d''', [SQLDelay]);
   Qry.ExecSQL;
   Writeln('No Timeout');
  except
   on E: Exception do
    Writeln(E.ClassName, ': ', E.Message);
  end;    
 finally
  Qry.Free;
  Conn.Free;
 end;
end;

begin
  try
   try
    CoInitialize(nil);
    TestADOCommandTimeout;
   finally
     CoUninitialize;
   end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
 Readln;
end.

输出:

 Connected to DB Waiting for 10 seconds, connection timeout is 5 seconds
 EOleException: Query timeout expired 
 Waiting for 10 seconds, query timeout is 30 seconds, connection timeout is 5 seconds  
 No Timeout 
 Waiting for 10 seconds, query timeout is 15 seconds, connection timeout is 15 seconds 
 No Timeout

【讨论】:

    猜你喜欢
    • 2021-09-15
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2017-05-28
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多