为什么主记录更改时 TADOQuery AfterOpen 事件不发生?
Why doesn't TADOQuery AfterOpen event occur when master record is changed?
假设我们有两个 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
This event is raised in other data access packages, such as BDE. Why does
this behavior differ for dbGo?
大多数其他数据访问包在这种情况下不会引发打开事件。例如,FireDAC 组件的帮助提到使用 OnMasterSetValues
(dbGo 组件不可用):
Use the OnMasterSetValues event handler to override parameter values
supplied to the detail dataset from the master dataset. Also, as the
BeforeOpen and AfterOpen events do not fire for a detail dataset,
OnMasterSetValues can be used instead.
因此不应触发打开事件,但某些数据访问组件会在这种情况下提供其他事件。
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
都不涉及关闭和重新打开
细节数据集。 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;
它使用 ADO RecordSet 对象的特定功能(也称为 Requery
)
在 TCustomADODataSet
的基础上检索匹配的详细记录,效率显着提高
而不是关闭并重新打开 Detail 数据集,这就是不调用其 AfterOpen
事件的原因。
另请参阅 DB.Pas 中定义的 TDetailDatalink
和 TMasterDatalink
。
假设我们有两个 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
This event is raised in other data access packages, such as BDE. Why does
this behavior differ for dbGo?
大多数其他数据访问包在这种情况下不会引发打开事件。例如,FireDAC 组件的帮助提到使用 OnMasterSetValues
(dbGo 组件不可用):
Use the OnMasterSetValues event handler to override parameter values supplied to the detail dataset from the master dataset. Also, as the BeforeOpen and AfterOpen events do not fire for a detail dataset, OnMasterSetValues can be used instead.
因此不应触发打开事件,但某些数据访问组件会在这种情况下提供其他事件。
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
都不涉及关闭和重新打开
细节数据集。 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;
它使用 ADO RecordSet 对象的特定功能(也称为 Requery
)
在 TCustomADODataSet
的基础上检索匹配的详细记录,效率显着提高
而不是关闭并重新打开 Detail 数据集,这就是不调用其 AfterOpen
事件的原因。
另请参阅 DB.Pas 中定义的 TDetailDatalink
和 TMasterDatalink
。