Почему не происходит событие TADOQuery AfterOpen при изменении основной записи? - PullRequest
4 голосов
/ 28 марта 2019

Предположим, у нас есть стандартное отношение «мастер-деталь» с двумя TADOQuery. Когда происходит навигация по основному набору данных, событие AfterOpen не возникает для подробного набора данных.

Это событие возникает в других пакетах доступа к данным, таких как BDE. Почему это поведение отличается для dbGo?

Часть .dfm:

  object DataSource1: TDataSource
    DataSet = SDQuery1
    Left = 504
    Top = 72
  end
  object DataSource2: TDataSource
    DataSet = SDQuery2
    Left = 520
    Top = 360
  end
  object ADOConnection1: TADOConnection
    LoginPrompt = False
    Left = 336
    Top = 464
  end
  object ADOQuery1: TADOQuery
    Connection = ADOConnection1
    Parameters = <>
    Left = 504
    Top = 160
  end
  object ADOQuery2: TADOQuery
    Connection = ADOConnection1
    AfterOpen = ADOQuery2AfterOpen // <- rised when dataset was opened at first time only
    DataSource = DataSource1
    Parameters = <>
    Left = 520
    Top = 296
  end

Ответы [ 2 ]

6 голосов
/ 28 марта 2019

Причина поведения компонентов Delphi ADO заключается в том, что при прокрутке набора основных данных этот код в ADODB.Pas выполняет

  procedure TCustomADODataSet.MasterChanged(Sender: TObject);
  begin
    if not Active then Exit;
    if Parameters.Count = 0 then
    begin
      CheckBrowseMode;
      if SetDetailFilter then First;
    end else
      RefreshParams;
  end;

, и ни SetDetailFilter, ни RefreshParams не требуют закрытия и повторного выполнения.- открытие набора данных Detail.Requery в конечном итоге вызывает

  procedure TCustomADODataSet.InternalRequery(Options: TExecuteOptions = []);
  begin
    if FConnectionChanged then
      DatabaseError(SCantRequery);
    try
      Recordset.Requery(ExecuteOptionsToOrd(Options));
    except
      if Recordset.State = adStateClosed then Close;
      raise;
    end;
    DestroyLookupCursor;
  end;

, который использует особую возможность (также называемую Requery) объекта ADO RecordSet, лежащую в основе TCustomADODataSet, для получения соответствующих подробных записей, что значительно более эффективно, чем закрытие иповторное открытие набора данных Detail, поэтому его событие AfterOpen не вызывается.

См. также TDetailDatalink и TMasterDatalink, определенные в DB.Pas.

3 голосов
/ 28 марта 2019
This event is raised in other data access packages, such as BDE. Why does 
this behavior differ for dbGo?

Большинство других пакетов доступа к данным не вызывают события open в этой ситуации. Например, в справке для компонентов FireDAC упоминается использование OnMasterSetValues (которое недоступно для компонентов dbGo):

Используйте обработчик события OnMasterSetValues ​​для переопределения значений параметров поставляется в подробный набор данных из основного набора данных. Кроме того, как События BeforeOpen и AfterOpen не запускаются для набора подробных данных, Вместо этого можно использовать OnMasterSetValues.

Таким образом, события open не должны запускаться, но некоторые компоненты доступа к данным предоставляют другие события в этой ситуации.

ref: FireDAC.Comp.DataSet.TFDDataSet.OnMasterSetValues ​​

...