Delphi:全局改变ADO命令超时



我们有一个巨大的Delphi 2005应用程序与大量的ADO组件(TADODataset, TADOStoredPRoc, TADOCommand…)分布在数百个表单。所有这些都连接到一个TADOConnection。

大多数组件都将CommandTimeout属性设置为默认值(30s),但少数组件将其设置为5分钟(300s),有些组件将其设置为永不超时(0s)。

我希望能够全局地更改所有ADO组件在应用程序范围内的设置。我更喜欢在运行时通过编程来实现,这样我就可以在每个安装的基础上调整超时,如果我需要的话

我希望我能在连接上找到一个全局事件,当一个ADO组件被创建/附加,在那里我可以调整命令超时,或者hack我的方式注入我的代码在组件本身,但出现空白。

我不想创建后代,因为我将不得不搜索/替换所有组件,如果我忘记使用后代而不是常规的ADO组件,我的超时将跟随应用程序的其余部分。

有谁知道怎么做吗?

如果所有ADO组件都放置在一个表单上,则可以使用Screen遍历所有表单。表单和屏幕。FormCount属性。对于每个表单,迭代其ComponentCount/Components属性并检查TADOCommand, TADODataSet, TADOQuery, TADOStoredProc和TADOTable。然后,您可以根据需要设置超时时间。当然,如果您动态创建表单,则必须单独考虑这一点。

下面的代码可以指导你。

procedure SetADOTimeout(ATimeout: Integer);
var
  cmp: TComponent;
  frm: TForm;
  I: Integer;
  J: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do begin
    frm := Screen.Forms[I];
    for J := 0 to frm.ComponentCount - 1 do begin
      cmp := frm.Components[J];
      if cmp is TADOCommand then
        TADOCommand(cmp).CommandTimeout := ATimeout
      else if cmp is TADODataSet then
        TADODataSet(cmp).CommandTimeout := ATimeout
      else if cmp is TADOQuery then
        TADOQuery(cmp).CommandTimeout := ATimeout
      else if cmp is TADOStoredProc then
        TADOStoredProc(cmp).CommandTimeout := ATimeout
      else if cmp is TADOTable then
        TADOTable(cmp).CommandTimeout := ATimeout;
    end;
  end;
end;

向所有阿根廷解决方案致敬!

为TADOConnection定义OnWillExecute事件处理器,并编写以下代码:

type
  TCustomADODataSetAccess = class(TCustomADODataSet);
procedure TYourDataModule.ADOConnectionWillExecute(...);
var
  i: Integer;
begin
  for i := 0 to ADOConnection.DataSetCount - 1 do
    TCustomADODataSetAccess(ADOConnection.DataSets[i]).CommandTimeout := Connection.CommandTimeout;
end;

这将为使用ADO连接的任何查询/表/存储过程设置命令超时时间。

根据文档,您可以使用CommandCountCommands来定位连接到TADOConnection的所有打开组件。

您的问题可能是动态创建表单。当创建表单时,您需要找到"某些东西"来挂钩,并检查该表单上的ADO组件。

如果您的表单来自自定义表单类,您可以在表单的constructorOnCreate事件中执行此操作。

如果没有,您可以查看TApplicationEvents并使用TApplication's OnIdle事件。

因为CommandTimeout是在TCustomADODataset类中引入的,你可以迭代每个表单/数据模块,找到一个TCustomADODataset和它的后代(ADODataset, ADOTable, ADOQuery),然后设置属性。

procedure SetADOCommandTimeOut(aTimeOut: integer);
var
  i, j: integer;
begin
  for i:= 0 to Screen.FormCount-1 do
  begin
    for j:= 0 to Forms[i].ComponentCount-1 do
      if Forms[i].Components[j] is TCustomADODataset then
        TCustomADODataset1(Forms[i].Components[j]).CommandTimeOut:= aTimeOut;
  end;
  for i:= 0 to Screen.DataModuleCount-1 do
  begin
    for j:= 0 to Datamodules[i].ComponentCount-1 do
      if Datamodules[i].Components[j] is TCustomADODataset then
        TCustomADODataset1(Datamodules[i].Components[j]).CommandTimeOut:= aTimeOut;
  end;
end;

注意:TCustomADODataset1就是TCustomADODataset,只是它有一个已发布的CommandTimeOut属性:

TCustomADODataset1 = class(TCustomADODataset)
published
  property CommandTimeOut;
end;

但是它只适用于已经创建的表单/数据模块。如果动态创建表单/数据模块,则必须在创建新表单/数据模块时应用它。一种方法是在Mainform中覆盖Notification,检查表单/数据模块的新创建,但这有点棘手,因为在创建时,还没有创建所有组件。你可以通过使用计时器延迟它一段时间来欺骗它(我不知道一个更优雅的方法-只是为了展示这个想法)

Procedure TMainForm.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (Operation = opInsert) and (
     ((AComponent is TForm) and not (aComponent is TMainForm)) // exclude MainForm 
     or (AComponent is TDataModule)
     ) then
  begin
    Timer1.Interval:= 2000; // 2 seconds ?
    Timer1.Enabled:= True;
  end;
end;
Procedure TMainForm.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled:= False;
  SetADOCommandTimeOut(MyTimeOut);
end;

您创建了数据模块层次结构?如果是这样,您可以在父级表单(所有其他数据模块都继承)上使用类似Uwe的答案的代码。

相关内容

  • 没有找到相关文章

最新更新