マスタ/詳細関係(M/D)

提供: Appmethod Topics
移動先: 案内検索

データセットの操作(FireDAC) への移動


FireDAC では、データセット間のマスタ/詳細関係を柔軟にサポートしています。

概要

マスタ/詳細関係を使用すると、現在のマスタ データセット レコードに基づいて詳細データセットを自動的にフィルタリングできます。たとえば、マスタ データセットに "Order" レコードがあり、詳細データセットに "Order Line" レコードがあるとしましょう。この場合、詳細データセットには現在の注文の明細行のみ表示されます。

マスタ データセットには特別なセットアップは必要ありません。

FireDAC には、マスタ/詳細関係の詳細データセットをセットアップする基本手法が以下のように 2 つ用意されています。

  • パラメータベース: マスタ データセット フィールド値が詳細 TFDQuery/TFDStoredProc パラメータに割り当てられたあと、詳細データセット クエリが再実行されます
  • 範囲ベース: マスタ データセット フィールド値は、詳細データセットに範囲を適用するのに使用されます。詳細データセットは、現在のアクティブなインデックスを持つ任意の FireDAC データセットの可能性があります。

これらの手法は組み合わせることができます。両者のどちらかを選択する場合は、以下の表を考慮に入れます。

特長 パラメータベース 範囲ベース
詳細クエリの結果、限られた数のレコードが返される。 +
詳細レコードは最新である。 +
マスタの変更ごとに発生するトラフィックと DBMS の処理負荷が軽減される。 +
キャッシュされた更新がマスタ変更時に保存される。 +
オフライン モードで動作する。 +
一元的キャッシュ更新とその伝播をサポートしている。 +

さらに、FireDAC には、マスタ/詳細関係のデータセットに対して "キャッシュされた更新" モードが以下のように 2 つ用意されています。

  • "分散的にキャッシュされた更新" モード: 各データセットでは、他のデータセットとは無関係に変更を追跡します。
  • "一元キャッシュ更新" モード: マスタ/詳細関係の少数のデータセットで単一の変更ログを共有します。マスタ データセットでは、自動インクリメント フィールド値も含め、変更を連鎖的に詳細データセットに伝播できます。

パラメータベースの M/D

パラメータベースの M/D 関係をセットアップするには、以下の手順を実行します。

  1. フォームに TFDQuery(またはその他の任意の FireDAC データセット)をドロップします。
  2. そのデータセットの名前を qOrders にします。これがマスタ データセットです。
  3. これをセットアップします - 以下のような SQL を割り当てます。
 SELECT * FROM {id Orders}
4. フォームに TDataSource をドロップします。それの名前を dsOrders とします。その DataSet プロパティを qOrders に設定します。
5. フォームに TFDQuery をドロップします。それの名前を qOrderDetails とします。これが詳細データセットです。
6. これをセットアップします - 以下のような SQL を割り当てます。
 SELECT * FROM {id Order Details} WHERE OrderID = :OrderID
7. そのあと、MasterSourcedsOrders に設定します。基本セットアップはこれで終わりです。

それで、これはどのように動作するのでしょうか。FireDAC が qOrderDetailsqOrders フィールドと qOrderDetails パラメータのペアのリストを作成します。各ペアの要素は、

  • MasterFields が指定されない場合は、同じ名前になります。
  • そうでない場合は、同じ位置、MasterFields リスト内の同じフィールド、Params コレクション内の同じパラメータになります。

現在の qOrders レコードが変更されると、FireDAC は各パラメータに、対応するフィールド値を割り当てます。今回の例では、qOrderDetails :OrderID パラメータが qOrder OrderID フィールド値を取ります。その後、qOrders が再実行されます。

メモ: BeforeOpen イベントと AfterOpen イベントは詳細データセットには発生しません。代わりに OnMasterSetValue を使用します。

範囲ベースの M/D

範囲パラメータベースの M/D 関係をセットアップするには、以下の手順を実行します。

  1. フォームに TFDQuery(またはその他の任意の FireDAC データセット)をドロップします。
  2. それの名前を qOrders にします。これがマスタ データセットです。
  3. これをセットアップします - 以下のような SQL を割り当てます。
 SELECT * FROM {id Orders}
4. フォームに TDataSource をドロップします。それの名前を dsOrders とします。DataSet プロパティを qOrders に設定します。
5. フォームに TFDQuery をドロップします。それの名前を qOrderDetails とします。これが詳細データセットです。
6. これをセットアップします - 以下のような SQL を割り当てます。
 SELECT * FROM {id Order Details}
7. MasterFieldsORDERID に設定し、IndexFieldNames を ORDERID に設定し、MasterSource を dsOrders に設定します。基本セットアップはこれで終わりです。

それで、これはどのように動作するのでしょうか。FireDAC が qOrderDetailsqOrders フィールドと qOrderDetails フィールドのペアのリストを作成します。各ペアのフィールドは同じ位置、MasterFields 内の同じマスタ フィールド、IndexFieldNames 内の同じ詳細フィールドになります。

現在の qOrders レコードが変更されると、FireDAC がその範囲を qOrderDetails に適用します。ここで、詳細フィールドが対応するマスタ フィールドと同じになります。今回の例では、qOrderDetails OrderID フィールドが qOrder OrderID フィールドと同じです。

手法の組み合わせ

両方の手法を組み合わせるには、アプリケーションでパラメータベースのセットアップと範囲ベースのセットアップの両方を使用し、fiDetailsFetchOptions.Cache に含めなければなりません。その場合、FireDAC は最初、範囲ベースの M/D を使用します。データセットが空であれば、FireDAC はパラメータベースの M/D を使用します。新たにクエリされたレコードは内部レコード記憶域に追加されます。

さらに、TFDDataSet.OnMasterSetValues イベント ハンドラを使用して M/D の動作をオーバーライドすることもできます。

詳細データセットの編集

新しいレコードが詳細データセットに挿入されると、M/D 関係に関与しているフィールドに、対応するマスタ データセット フィールド値が自動的に設定されます。詳細データセット フィールド リストは以下のように定義されます。

  • パラメータベース M/D の場合は、DetailFields(指定時)。未指定時は、同じ名前をパラメータとするフィールド。
  • 範囲ベース M/D の場合は、インデックス フィールド。

詳細レコードを挿入するには、マスタ データセットが閲覧状態dsBrowse)になければなりません。マスタ データセットと詳細データセットの両方を挿入状態(dsInsert)または編集状態(dsEdit)にすることはできません。

マスタ データセットと詳細データセットが "キャッシュされた更新" モードにある場合は、アプリケーションで TFDSchemaAdapter を使用して、一元キャッシュ更新とその伝播を有効にすることができます。さらに言えば、マスタ データセットと詳細データセットの SchemaAdapter プロパティが同じ TFDSchemaAdapter を指している必要があり、詳細データセットの FetchOptions.DetailCascadeTrue にします。

M/D 内のナビゲーション

アプリケーションでマスタ データセット内をナビゲートする必要がある場合、詳細データセットはマスタ レコードが変更されるたびに更新されます。この処理はリソースを消費し、ナビゲーションが遅くなるおそれがあります。M/D の同期を一時的に無効にするには、アプリケーションでマスタ データセットに対して、以下のように DisableControls(有効に戻すには EnableControls)を呼び出します。

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

M/D の同期を強制的に無効にする場合は、マスタ データセットに対して ApplyMaster メソッドを呼び出します。特定の詳細データセットに対して M/D の同期を一時的に無効にするには、以下のように、そのデータセットの MasterLink プロパティの DisableScroll(有効に戻す場合は EnableScroll)メソッドを使用します。

 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;

GUI アプリケーションでは、M/D の遅延同期が役に立つ場合があります。そのため、ユーザーがグリッド内をスクロールした場合、詳細データセットはすぐには更新されず、他のナビゲーションがない場合にのみ、少し遅れて更新されます。遅延同期を使用するには、詳細データセットの FetchOptions.DetailDelay を設定します。特定の詳細データセットに対して M/D の遅延同期を一時的に無効にして即時同期を使用するには、MasterLink プロパティの DisableDelayedScroll(有効に戻す場合は EnableDelayedScroll)メソッドを使用します。

デフォルトでは、状態変化、キーでないフィールドの値の変化、マスタ データセットの更新のどれが起こっても、詳細データセットの更新は行われません。このようになっているため、詳細データセットの余分な更新を避けることができます。アプリケーションで詳細データセットを常に更新すると想定する場合は、FetchOptions.DetailOptimizeFalse に設定します。

関連項目

詳細については、次のデモを参照してください。

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