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

提供: RAD Studio
移動先: 案内検索

データセットの操作(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 が qOrderDetails に、qOrders フィールドと 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 と名前を付けます。 DataSetqOrders に設定します。
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 の場合 - インデックス フィールド。

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

マスタ データセットと詳細データセットが "キャッシュされた更新" モードにある場合は、アプリケーションで TFDSchemaAdapterd を使用して、一元キャッシュ更新とその伝播を有効にすることができます。さらに言えば、マスタ データセットと詳細データセットの 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 に設定します。

関連項目

サンプル