AnyDAC has flexible support for master-detail relationship between datasets.
The master-detail relationship allows automatically filter a detail dataset basing on a current master dataset record. For example, the master dataset has "Order" records, and the detail dataset has "Order Line" records. So the detail dataset shows only lines for the current order.
Special setup is not required for a master dataset. AnyDAC offers two base methods to setup a detail dataset in a master-detail relationship:
These methods may be combined. To choose between them consider the table:
|
Feature |
Parameter based |
Range based |
|
The detail query returns a limited number of records. |
+ |
|
|
The detail records are fresh. |
+ |
|
|
Reduced traffic and DBMS workload on each master change. |
|
+ |
|
The cached updates preserved on the master change. |
|
+ |
|
Works in offline mode. |
|
+ |
|
Supports Centralized Cached Updates with propagation |
|
+ |
Also, AnyDAC offers two cached updates modes for the datasets in master-detail relationship:
To setup the parameters based M/D relationship, perform the following steps:
SELECT * FROM {id Orders}
SELECT * FROM {id Order Details} WHERE OrderID = :OrderID
Then set MasterSource to dsOrders. The base setup is finished.
So, how it works ? AnyDAC builds for qOrderDetails a list of pairs - qOrders fields and qOrderDetails parameters. Elements in each pair:
When the current qOrders record is changed, AnyDAC assigns for each parameter a corresponding field value. In our case qOrderDetails :OrderID parameter gets the qOrder OrderID field value. After that the qOrders is reexecuted.
Note, the BeforeOpen and AfterOpen events do not fire for detail dataset. Use OnMasterSetValue instead.
To setup the range based M/D relationship, perform the following steps:
SELECT * FROM {id Orders}
SELECT * FROM {id Order Details}
Then set MasterFields to ORDERID, IndexFieldNames to ORDERID and MasterSource to dsOrders. The base setup is finished.
So, how it works ? AnyDAC builds for qOrderDetails a list of pairs - qOrders and qOrderDetails fields, where fields in each pair have the same position, master fields in MasterFields, detail fields in IndexFieldNames.
When the current qOrders record is changed, AnyDAC applies the range to qOrderDetails, where details fields are equal to corresponding master fields. In our case qOrderDetails OrderID field is equal to qOrder OrderID field.
To combine both methods an application should use both Parameters and Range based setups and include fiDetails into FetchOptions.Cache. Then AnyDAC at first will use range based M/D. And if a dataset is empty, then AnyDAC will use parameters based M/D. The new queried records will be appended to the internal records storage.
Also the OnMasterSetValues event handler may be used to override M/D behavior.
When a new record is inserted into detail dataset, the fields participating in a M/D relationship will be filled automatically by the corresponding master dataset field values. The detail dataset field list is defined:
To insert a detail record, the master dataset must be in the browsing state (dsBrowse). It is impossible to have both master and detail dataset in inserting (dsInsert) or editing (dsEdit) state.
When master and details datasets are in the cached updates mode, then application may use TADSchemaAdapter to enable Centralized Cached Updates with propagation. For that master and details datasets SchemaAdapter property must point to the same TADSchemaAdapter and detail dataset FetchOptions.DetailCascade is True.
When an application needs to navigate in a master dataset, on each master record change the detail dataset will be refreshed. That consumes the resources and the navigation may be slow. To temporary disable M/D synchronization, application may call DisableControls / EnableControls for the master dataset:
qOrders.DisableControls; try qOrders.First; while not qOrders.Eof do begin ..... qOrders.Next; end; finally qOrders.EnableControls; end;
To force disabled M/D synchronization, call ApplyMaster method on the master dataset. To temporary disable M/D synchronization for a specific detail dataset, use DisableScroll / EnableScroll methods of the dataset MasterLink property:
qOrderDetails.MasterLink.DisableScroll; try qOrders.First; while not qOrders.Eof do begin if qOrders.FieldByName('OrderID').AsInteger = 100 then begin qOrderDetails.ApplyMaster; // read qOrderDetails dataset - it is synchronized with qOrders end; qOrders.Next; end; finally qOrderDetails.MasterLink.EnableScroll; end;
The GUI applications may benefit from delayed M/D synchronization. So, when an user scrolls in a grid, a detail dataset will be refreshed not immediately, but after some delay and if there were no other navigations. To use that set FetchOptions.DetailDelay for a detail dataset. To temporary disable delayed M/D synchronization for a specific detail dataset and use immediate synchronization, use DisableDelayedScroll / EnableDelayedScroll methods of the MasterLink property.
By default a state change, a non-key field values change, refreshing of master dataset will not lead to detail dataset refreshing. This avoids extra refreshes of detail dataset. If your application expects always refresh detail dataset, then set FetchOptions.DetailOptimize to False.
See the following demos for additional details:
|
What do you think about this topic? Send feedback!
|