Delphi:全局更改ADO命令超时

发布于 2024-12-05 11:18:01 字数 475 浏览 1 评论 0原文

我们有一个巨大的 Delphi 2005 应用程序,其中包含大量 ADO 组件(TADODataset、TADOStoredPROc、TADOCommand...),分布在数百个表单上。它们全部连接到单个 TADOConnection。

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

我希望能够在应用程序范围内全局更改所有 ADO 组件的此设置。我更喜欢在运行时以编程方式执行此操作,以便在需要时可以在每次安装的基础上调整超时。

我希望在创建/附加 ADO 组件时可以在连接上找到一个全局事件,我可以在其中调整命令超时,或者破解我的方式将我的代码注入组件本身,但结果是空白。

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

有人知道我们如何做到这一点吗?

We have a HUGE Delphi 2005 application with LOTS of ADO components (TADODataset, TADOStoredPRoc, TADOCommand...) spread on hundreads of forms. All of them are connected to a SINGLE TADOConnection.

Most of these components have their CommandTimeout property set to the default (30s) but a few have it set to 5 minutes (300s) and some are set to never timeout (0s).

I'd like to be able to globally change this setting for all ADO components application-wide. I'd prefer to do it programmatically at runtime so that I could tweak the timeouts on a per-installation basis if I need to.

I was hoping I could find a global event on the connection when an ADO component is created/attached, where I could tweak the commandtimeout, or hack my way into injecting my code in the components themselves, but came up blank.

I don't want to create decendants because I'll have to search/replace trought all the components, and if I ever forget to use the descendants instead of the regular ADO components my timeout wont follow the rest of the application.

Anybody has an idea how we could do this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

伏妖词 2024-12-12 11:18:01

如果所有 ADO 组件都放置在窗体上,则可以使用 Screen.Forms 和 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;

If all of you ADO components are placed on a form, you can iterate over all forms using the Screen.Forms and Screen.FormCount properties. For each form iterate over its ComponentCount/Components property and check for TADOCommand, TADODataSet, TADOQuery, TADOStoredProc and TADOTable. Then you can set the timeout as you wish. Of course, if you create forms dynamically you have to take this into account separately.

The following code may guide you.

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;
混吃等死 2024-12-12 11:18:01

向所有阿根廷解决方案致以问候!

只需为您拥有的 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 连接的任何查询/表/存储过程设置命令超时。

Greetings to all Argentinian solutions!

Just define the OnWillExecute event handler for the TADOConnection you have and write following code:

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;

This will set the command timeout for any query/table/stored procedure which uses your ADO connection.

絕版丫頭 2024-12-12 11:18:01

根据文档,您可以使用 CommandCountCommands 来查找附加到 TADOConnection 的所有打开组件。

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

如果您的表单源自自定义表单类,则可以在表单的构造函数OnCreate 事件中执行此操作。

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

According to the documentation, you can use CommandCount and Commands to locate all the open components attached to your TADOConnection.

Your problem is likely to be dynamically created forms. You'll need to find "something" to hook when a form is created and check for ADO components on that form.

If your forms descend from a custom form class, you could do this in the form's constructor or OnCreate event.

If not, you could look at TApplicationEvents and using the TApplication's OnIdle event.

遗失的美好 2024-12-12 11:18:01

由于 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;

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

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;

Since CommandTimeout is introduced in the TCustomADODataset class, you can iterate for each form/datamodule, find a TCustomADODataset and it's descendants (ADODataset, ADOTable, ADOQuery) then set the Property.

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;

Note: TCustomADODataset1 is exactly TCustomADODataset, only it has a published CommandTimeOut property :

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

But it's only applied to forms/datamodules which are already created. If you create your forms/datamodules dynamically, then you must apply it whenever a new form/datamodule is created.
One way to do it is by override Notification in your Mainform, checking for a new a creation of form/datamodule, but this a little bit tricky since at the the creation time, all the components are not created yet. You trick it by delay it for a while using a timer (I don't know a more elegant way - just to show the idea)

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;
聆听风音 2024-12-12 11:18:01

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

You create datamodule hierarchies? If so, you can use code like Uwe's answer on your patriarch form (which all other datamodules inherit).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文