QDataSet 做为 QDB 的重要组成部分,目前已经支持主从表的设定。QDataSet 的主从表支持与一般的数据集略有不同,我做了一些简化和增强处理。设定主从表第一步与一般的数据集没有什么不同,设置从表的 MasterSource 为主表的数据源( DataSource ),但接下来就有所不同了:
1、直接通过设置 MasterFields 来激活主从关系
MasterFields 的格式进行了增强,不再是分别设置 MasterFields 和 IndexFields 。直接设定关键字段关联即可,格式为:
主表字段=从表字段[;主表字段=从表字段]…
如果主表字段和从表字段名一样,可以只写主表字段,多个字段间通过分号或逗号直接分隔即可,示例如下:
FDetailDataSet.MasterSource := DataSource1; FDetailDataSet.MasterFields := 'id=MasterId';
2、通过 OnMasterChanged 事件来获取从表数据
OnMasterChanged 事件在主表记录变更后会触发一次,所以在我们并不想一次性获取到所有的从表数据时,我们可以通过响应这一事件来动态获取明细数据,如:
... FDetailDataSet.OnMasterChanged := DoMasterChanged; FDetailDataSet.MasterSource := DataSource1; ... rocedure TForm1.DoMasterChanged(ADataSet: TDataSet); begin FProv.OpenDataSet(FDetailDataSet, 'select * from pg_attribute where attrelid=' + FMasterDataSet.FieldByName('oid').AsString); end;
好了,方法2虽然每次只取部分明细记录,但问题是当我们重复浏览记录时,还会需要重复查询。这显然与我们减少网络数据传输的思路是背道而驰的,所以,我们可以进一步优化:
procedure TForm1.DoMasterChanged(ADataSet: TDataSet); var S: QStringW; ASub: TQDataSet; I: Integer; begin try Inc(FRequests); S := 'select * from pg_attribute where attrelid=' + FMasterDataSet.FieldByName('oid').AsString; for I := 0 to FDetailDataSet.RecordsetCount - 1 do begin if FDetailDataSet.Recordsets[I].CommandText = S then begin FDetailDataSet.ActiveRecordset := I; Inc(FHits); Exit; end; end; ASub := FProv.OpenDataSet(S); FDetailDataSet.AddDataSet(ASub); FDetailDataSet.ActiveRecordset := FDetailDataSet.RecordsetCount - 1; finally Panel2.Caption := '总计: ' + IntToStr(FRequests) + ' 次请求,缓存命中:' + IntToStr(FHits) + '次'; end; end;
这里我加入了一个统计来计算减少查询的次数,看效果吧: