Haupt/Detail-Beziehung (H/D)

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu Arbeiten mit Datenmengen (FireDAC)


FireDAC stellt eine flexible Unterstützung für Haupt/Detail-Beziehungen zwischen Datenmengen bereit.

Allgemeine Informationen

Die Haupt/Detail-Beziehung ermöglicht eine automatische Filterung einer Detaildatenmenge auf Basis eines aktuellen Datensatzes der Hauptdatenmenge. Zum Beispiel: Die Hauptdatenmenge enthält Datensätze zu "Aufträgen" und die Detaildatenmenge Datensätze zu "Auftragspostionen". Die Detaildatenmenge zeigt dann nur Positionen für den aktuellen Auftrag an.

Für eine Hauptdatenmenge ist keine spezielle Konfiguration erforderlich.

FireDAC bietet zwei grundlegende Methoden zum Einrichten einer Detaildatenmenge in einer Haupt/Detail-Beziehung:

  • Parameterbasiert. Die Feldwerte der Hauptdatenmenge werden den Parametern der Detail-TFDQuery oder -TFDStoredProc zugewiesen, und dann wird die Detaildatenmengen-Abfrage erneut ausgeführt.
  • Bereichsbasiert. Die Feldwerte der Hauptdatenmenge werden verwendet, um für die Detaildatenmenge einen Bereich festzulegen. Die Detaildatenmenge kann eine beliebige FireDAC-Datenmenge mit einem aktuellen aktiven Index sein.

Diese Methoden können kombiniert werden. In welchen Fällen welche Methode verwendet werden sollte, können Sie der folgenden Tabelle entnehmen:

Feature Parameterbasiert   Bereichsbasiert  
Die Detailabfrage gibt eine begrenzte Anzahl von Datensätzen zurück. +
Die Detaildatensätze sind unverändert. +
Reduzierter Datenverkehr und reduzierte DBMS-Auslastung bei jeder Änderung der Hauptdatenmenge. +
Die zwischengespeicherten Aktualisierungen bleiben bei Änderungen der Hauptdatenmenge erhalten. +
Arbeitet im Offline-Modus. +
Unterstützt zentralisierte zwischengespeicherte Aktualisierungen mit Weitergabe +

Außerdem bietet FireDAC zwei Modi für zwischengespeicherte Aktualisierungen für die Datenmengen in einer Haupt/Detail-Beziehung:

  • Dezentralisierte zwischengespeicherte Aktualisierungen: Jede Datenmenge verfolgt die Änderungen unabhängig von anderen Datenmengen.
  • Zentralisierte zwischengespeicherte Aktualisierungen: Datenmengen in einer Haupt/Detail-Beziehung verwenden ein gemeinsames Änderungsprotokoll. Die Hauptdatenmenge kann Änderungen an die Detaildatenmengen stufenweise weitergeben, einschließlich von Zählerfeldwerten (Autoinkrement).

Parameterbasierte H/D

Gehen Sie folgendermaßen vor, um eine parameterbasierte H/D-Beziehung einzurichten:

  1. Legen Sie TFDQuery (oder eine andere FireDAC-Datenmenge) auf einem Formular ab.
  2. Geben Sie der Datenmenge den Namen qOrders. Dies ist die Hauptdatenmenge.
  3. Richten Sie sie ein – weisen Sie den folgenden SQL-Code zu:
 SELECT * FROM {id Orders}
4. Legen Sie eine TDataSource-Komponente auf einem Formular ab. Nennen Sie sie dsOrders. Setzen Sie die Eigenschaft DataSet auf qOrders.
5. Ziehen Sie eine TFDQuery-Komponente auf ein Formular. Nennen Sie sie qOrderDetails. Das ist die Detaildatenmenge.
6. Richten Sie sie ein – weisen Sie den folgenden SQL-Code zu:
 SELECT * FROM {id Order Details} WHERE OrderID = :OrderID
7. Setzen Sie dann MasterSource auf dsOrders. Die grundlegende Einrichtung ist damit abgeschlossen.

Funktionsweise: FireDAC erstellt für qOrderDetails eine Liste mit Paaren – qOrders-Felder und qOrderDetails-Parameter. Elemente in jedem Paar:

  • Wenn MasterFields nicht angegeben ist, dann haben sie denselben Namen;
  • Ansonsten haben die Paarelemente dieselbe Position, dieselben Felder in der MasterFields-Liste und dieselben Parameter in der Params-Kollektion.

Wenn der aktuelle qOrders-Datensatz geändert wird, weist FireDAC für jeden Parameter einen entsprechenden Feldwert zu. In diesem Fall erhält der Parameter qOrderDetails :OrderID den Feldwert qOrder OrderID. Danach wird qOrders erneut ausgeführt.

Hinweis: Die Ereignisse BeforeOpen und AfterOpen werden für eine Detaildatenmenge nicht ausgelöst. Verwenden Sie stattdessen OnMasterSetValue.

Bereichsbasierte H/D

Gehen Sie folgendermaßen vor, um eine bereichsbasierte H/D-Beziehung einzurichten:

  1. Legen Sie TFDQuery (oder eine andere FireDAC-Datenmenge) auf einem Formular ab.
  2. Nennen Sie die Datenmenge qOrders. Dies ist die Hauptdatenmenge.
  3. Richten Sie sie ein – weisen Sie den folgenden SQL-Code zu:
 SELECT * FROM {id Orders}
4. Legen Sie eine TDataSource-Komponente auf einem Formular ab. Nennen Sie sie dsOrders. Setzen Sie die Eigenschaft DataSet auf qOrders.
5. Ziehen Sie eine TFDQuery-Komponente auf ein Formular. Nennen Sie sie qOrderDetails. Das ist die Detaildatenmenge.
6. Richten Sie sie ein – weisen Sie den folgenden SQL-Code zu:
 SELECT * FROM {id Order Details}
7. Setzen Sie MasterFields auf ORDERID, setzen Sie IndexFieldNames auf ORDERID, und setzen Sie MasterSource auf dsOrders. Die grundlegende Einrichtung ist damit abgeschlossen.

Funktionsweise: FireDAC erstellt für qOrderDetails eine Liste mit Paaren – qOrders- und qOrderDetails-Felder. Die Felder in jedem Paar haben dieselbe Position, Hauptfelder in MasterFields und Detailfelder in IndexFieldNames.

Wenn der aktuelle qOrders-Datensatz geändert wird, übernimmt FireDAC den Bereich für qOrderDetails, wobei Detailfelder identisch mit den entsprechenden Hauptfeldern sind. In diesem Fall ist das Feld qOrderDetails OrderID identisch mit dem Feld qOrder OrderID.

Kombinieren von Methoden

Um beide Methoden zu kombinieren, muss eine Anwendung sowohl parameter- als bereichsbasiert eingerichtet werden, und fiDetails muss in FetchOptions.Cache aufgenommen werden. FireDAC verwendet dann zuerst die bereichsbasierte H/D. Und falls eine Datenmenge leer ist, verwendet FireDAC die parameterbasierte H/D. Die neuen abgefragten Datensätze werden an den internen Datensatzspeicher angehängt.

Sie können auch mit der Ereignisbehandlungsroutine TFDDataSet.OnMasterSetValues das H/D-Verhalten überschreiben.

Bearbeiten von Detaildatenmengen

Wenn ein neuer Datensatz in eine Detaildatenmenge eingefügt wird, werden die Felder, die für die H/D-Beziehung verwendet werden, automatisch mit den Feldwerten der zugehörigen Hauptdatenmenge gefüllt. Die Felderliste der Detaildatenmenge ist definiert:

  • Für parameterbasierte H/D – DetailFields, falls angegeben. Ansonsten – die Felder mit denselben Namen wie die Parameter.
  • Für bereichsbasierte H/D – die Indexfelder.

Um einen Detaildatensatz einzufügen, muss sich die Hauptdatenmenge im Anzeigemodus befinden (dsBrowse). Es ist nicht möglich, dass sich sowohl die Haupt- als die Detaildatenmenge im Einfüge- (dsInsert) oder Bearbeitungsmodus (dsEdit) befindet.

Wenn Haupt- und Detaildatenmengen sich im zwischengespeicherten Aktualisierungsmodus befinden, dann kann die Anwendung mit TFDSchemaAdapter zentralisierte zwischengespeicherte Aktualisierungen mit Weitergabe verwenden. Dazu muss die Eigenschaft SchemaAdapter der Haupt- und Detaildatenmengen auf denselben TFDSchemaAdapter zeigen, und FetchOptions.DetailCascade der Detaildatenmenge ist True.

Navigieren in H/D

Wenn eine Anwendung in einer Hauptdatenmenge navigieren muss, wird die Detaildatenmenge bei jeder Änderung des Hauptdatensatzes aktualisiert. Dieser Vorgang verbraucht Ressourcen, und die Navigation kann sehr langsam sein. Um die H/D-Synchronisierung vorübergehend zu deaktivieren, kann eine Anwendung DisableControls/EnableControls für die Hauptdatenmenge aufrufen:

 qOrders.DisableControls;
 try
   qOrders.First;
   while not qOrders.Eof do begin
     .....
     qOrders.Next;
   end;
 finally
   qOrders.EnableControls;
 end;

Rufen Sie die Methode ApplyMaster für die Hauptdatenmenge auf, um eine deaktivierte H/D-Synchronisierung zu ermöglichen. Mit der Methode DisableScroll/EnableScroll der Eigenschaft MasterLink der Datenmenge können Sie die H/D-Synchronisierung für eine bestimmte Detaildatenmenge vorübergehend deaktivieren:

 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;

Die verzögerte H/D-Synchronisierung kann für GUI-Anwendungen von Vorteil sein. Wenn ein Benutzer beispielsweise in einer Tabelle einen Bildlauf durchführt, wird eine Detaildatenmenge nicht sofort aktualisiert, sondern erst nach einer Verzögerung und nur dann, wenn keine weitere Navigation erfolgt. Setzen Sie zur Verwendung der verzögerten Synchronisierung FetchOptions.DetailDelay für eine Detaildatenmenge. Mit der Methode DisableDelayedScroll/EnableDelayedScroll der Eigenschaft MasterLink können Sie die verzögerte H/D-Synchronisierung für eine bestimmte Detaildatenmenge vorübergehend deaktivieren und die sofortige Synchronisierung verwenden.

Eine Statusänderung, eine Änderung eines Nicht-Schlüsselfeldwertes oder die Aktualisierung der Hauptdatenmenge führt nicht zu einer Aktualisierung der Detaildatenmenge. Dadurch werden zusätzliche Aktualisierungen der Detaildatenmenge vermieden. Wenn in Ihrer Anwendung Detaildatenmengen immer aktualisiert werden sollen, setzen Sie FetchOptions.DetailOptimize auf False.

Siehe auch

Beispiel

Die folgenden Demos enthalten weitere Einzelheiten dazu:

  • FireDAC\Samples\Comp Layer\TFDQuery\MasterDetail
  • FireDAC\Samples\Comp Layer\TFDMemTable\MasterDetail