我们有一个巨大的Delphi 2005应用程序,其中有大量的ADO组件(TADODataset,TADOStoredPRoc,TADOCommand ...)在表单的hundreads上传播。所有这些都连接到SINGLE TADOConnection。
这些组件中的大多数将其CommandTimeout属性设置为默认值(30秒),但有一些设置为5分钟(300秒),有些设置为永不超时(0秒)。
我希望能够全局更改应用程序范围内所有ADO组件的此设置。我更喜欢在运行时以编程方式执行此操作,以便我可以根据需要调整每次安装的超时。
我希望在创建/附加ADO组件时可以在连接上找到全局事件,在那里我可以调整命令时间,或者破解我在组件本身中注入代码的方式,但是空白了。 / p>
我不想创建后代,因为我必须搜索/替换所有组件,如果我忘记使用后代而不是常规ADO组件,我的超时将不会跟随应用程序的其余部分。
任何人都知道我们该如何做到这一点?
答案 0 :(得分:3)
如果所有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;
答案 1 :(得分:1)
向所有阿根廷解决方案致以问候!
只需为您拥有的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连接的任何查询/表/存储过程设置命令超时。
答案 2 :(得分:0)
根据文档,您可以使用CommandCount
和Commands
找到附加到TADOConnection
的所有打开的组件。
您的问题很可能是动态创建的表单。在创建表单时,您需要找到要挂钩的“东西”并检查该表单上的ADO组件。
如果您的表单来自自定义表单类,则可以在表单的constructor
或OnCreate
事件中执行此操作。
如果没有,您可以查看TApplicationEvents
并使用TApplication's OnIdle
事件。
答案 3 :(得分:0)
由于在TCustomADODataset类中引入了CommandTimeout,您可以迭代每个表单/数据模块,找到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,检查一个新的form / datamodule创建,但这有点棘手,因为在创建时,所有组件都没有创建。你通过使用计时器延迟一段时间来欺骗它(我不知道更优雅的方式 - 只是为了表明这个想法)
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;
答案 4 :(得分:0)
您是否创建了数据模块层次结构?如果是这样,你可以在你的族长表格(所有其他数据模块都继承)上使用像Uwe的答案这样的代码。