Delphi: глобально изменить время ожидания команды ADO - PullRequest
2 голосов
/ 19 сентября 2011

У нас огромное приложение Delphi 2005 с множеством компонентов ADO (TADODataset, TADOStoredPRoc, TADOCommand ...), распределенных по множеству форм.Все они подключены к ОДНОМУ TADOConnection.

Для большинства этих компонентов свойство CommandTimeout имеет значение по умолчанию (30 с), но для некоторых из них установлено значение 5 минут (300 с), а для некоторых - никогда не превышать время ожидания(0 с).

Я хотел бы иметь возможность глобально изменить этот параметр для всех компонентов ADO для всего приложения.Я бы предпочел сделать это программно во время выполнения, чтобы при необходимости можно было настроить таймауты для каждой установки.

Я надеялся, что смогу найти глобальное событие в соединении, когда компонент ADOсоздается / присоединяется, где я мог бы настроить время ожидания команды или взломать свой путь для внедрения кода в сами компоненты, но оказалось пустым.

Я не хочу создавать потомков, потому что мне придетсяискать / заменять все компоненты, и если я когда-нибудь забуду использовать потомков вместо обычных компонентов ADO, мой тайм-аут не будет соответствовать остальной части приложения.

У кого-нибудь есть идеи, как мы можем это сделать?

Ответы [ 5 ]

3 голосов
/ 19 сентября 2011

Если все компоненты 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 голос
/ 27 марта 2015

Приветствую всех аргентинских решений!

Просто определите обработчик события OnWillExecute для имеющегося соединения TADOConnection и напишите следующий код:

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.

0 голосов
/ 20 сентября 2011

Вы создаете иерархии модулей данных? Если это так, вы можете использовать код, подобный ответу Уве, в форме патриарха (который наследуют все другие модули данных).

0 голосов
/ 19 сентября 2011

Поскольку 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;
0 голосов
/ 19 сентября 2011

Согласно документации, вы можете использовать CommandCount и Commands, чтобы найти все открытые компоненты, подключенные к вашему TADOConnection.

Ваша проблема может быть динамическисозданные формы.Вам нужно будет найти «что-то», чтобы перехватить его при создании формы, и проверить наличие компонентов ADO в этой форме.

Если ваши формы происходят от пользовательского класса форм, вы можете сделать это в форме constructor или OnCreate событие.

Если нет, вы можете посмотреть на TApplicationEvents и использовать событие TApplication's OnIdle.

...