mcpField
A
add-sample-data

add-sample-data

github.com/microsoftデータ・データベース1.1k231 回インストール今日更新
リポジトリ

add-sample-data について

add-sample-dataは、Power PagesのコードアプリでDataverseテーブルにデータを追加するスキルです。承認済みのテーブル範囲に沿って状況に合うレコードを生成し、依存順に挿入します。プロトタイプのシードデータも再利用できます。

主な機能

  1. 01承認済み範囲からテーブルを選択
  2. 02依存順にレコードを挿入
  3. 03状況に合うサンプルデータを生成
  4. 04プロトタイプのシードデータを再利用
  5. 05目標件数に達したテーブルを除外
  6. 06一部失敗後の安全な再実行

活用シーン

  1. 01新規Dataverseテーブルへのデモデータ追加
  2. 02プロトタイプのシードデータをDataverseに対応付け
  3. 03挿入失敗後にデータ追加を再開

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/microsoft/power-platform-skills --skill add-sample-data

インストール後、Claude Code で/add-sample-dataを入力して読み込まれたか確認します。

詳細

プラグインチェック:node "${PLUGIN_ROOT}/scripts/check-version.js" を実行します。メッセージが出力された場合は、続行する前にユーザーに表示してください。

📋 共通の指示:shared-instructions.md — 最初にお読みください。

サンプルデータの追加

アプリのルート:プロジェクトの読み取りやコマンドの実行を行う前に、 app-working-directory.mdを実行してください。 メディアのパスや再試行を含む、すべてのシェル呼び出しとファイルツールで、解決された絶対パスの working_dir を使用してください。 以前の cd の状態を引き継がないでください。

Dataverse テーブルに現実的なサンプルレコードを入力し、新しくスキャフォールディングされたコードアプリを初回起動したときに、実際のデータのように表示されるようにします。各テーブルのスキーマから行を生成し、依存関係の順に挿入します。テーブルが作成された後、/add-dataverse(または /setup-datamodel)の後に使用してください。

基本原則

  • マニフェスト全体ではなく、承認された範囲内を網羅します。 対象となる承認済みテーブルごとに、少量の有用なデータセットを用意してください。マニフェストは検証済みのアプリインベントリであり、廃止予定のテーブルや無関係なテーブルが含まれる場合があります。マニフェストに存在するからといって、それらにデータを投入する許可があるわけではありません。範囲と廃止に関する除外は、以下の網羅性、ファンアウト、プロトタイプの再利用、メディア、再試行に関するすべてのルールに優先します。
  • 挿入順序が重要です。 ルックアップ ID を利用できるように、親テーブル/参照先テーブルを子テーブル/参照元テーブルより先に挿入してください。
  • Lorem Ipsum ではなく、文脈に合ったデータを使用します。 列名と型に合った値を生成してください。検査アプリの cr3e9_sitename 列には、「Sample Name 1」ではなく「Westside Construction Site」を設定します。
  • シナリオに応じた行を用意します。 native-app-plan.md がある場合は、特に screen-templates.mdで定義されている ### Shared Conventions と画面ごとの Operational pattern の値を確認してください。ない場合は、現在のデータリクエストと検証済みのスキーマを使用してください。サンプル行では、アプリの実際のワークフローを反映してください。ステータス、日付、リレーションシップ、優先度/重大度、メディアのメタデータや、計画された最初のビューポートを際立たせるエッジケースを含めます。
  • 失敗しても処理を続行します。 挿入に失敗した場合はエラーを記録し、残りのレコードの処理を続けてください。自動ロールバックは行わないでください。ユーザーは問題を修正した後に再実行できます。
  • 再実行しても重複させません。 前回の実行が一部だけ完了している場合は、2回目の実行で memory-bank.md のサンプルデータテーブルを確認し、挿入済みのレコードをスキップします。
  • ソリューションのスコープ内で挿入します。 レコードがデフォルトではなくこちらのソリューションに登録されるよう、必ず --solution <uniqueName> を指定してください。

ワークフロー

  1. 承認済みのサンプルデータ範囲を解決 → 1. プロジェクトと認証を検証 → 2. 対象範囲内のテーブルを検出 → 3. テーブルと件数を選択 → 4. 生成してプレビュー → 5. 挿入 → 6. 要約
ステップ 0 — 承認済みシード範囲を確定する

入力はスキル引数であり、dataverse-request.js のフラグではありません。

  • --working-dir <absolute-root>:呼び出し元のルートを引き継ぎます。明示されたルートと継承されたルートが競合する場合は拒否します。ネストされた呼び出しでシェルの cwd をデフォルトとして使用してはいけません。
  • --tables <comma-separated-logical-names>:承認済みシードテーブルの正確な許可リストです。新規作成の場合も含め、オーケストレーションされたすべての呼び出しで必須です。
  • --exclude-tables <comma-separated-logical-names>:承認済み編集から廃止するテーブル名です。廃止するものがない場合に限り、省略するか、明示的な空文字列を渡します。

オーケストレーションされた呼び出しでは、認証、レコード数のクエリ、生成を行う前に、スコープが指定された引き継ぎと一致する --tables が必要です。許可リストがない、または不正な形式の場合は NEEDS_CONTEXT を返します。すべてのマニフェストテーブルにフォールバックしてはいけません。明示的に空の許可リストが指定された場合は何もしません。承認済みシードテーブルがないことを報告し、クラウドへの呼び出しや書き込みを行わずに戻ります。

論理名をマニフェストおよび承認済みプラン/呼び出し元のスコープと照合して検証します。呼び出し元の廃止対象セットと、現在のプラン/履歴に記録された保留中の削除から retiringTables を構築し、これらを --exclude-tables に含めます。許可リストの名前が存在しない、または未検証である場合や、retiringTables と重複する場合は、挿入前に停止し、スコープの不一致を返します。不明な名前を黙って除外したり、移行中のマニフェスト項目から権限を推測したりしてはいけません。

スタンドアロンのリクエストでは、明示的な --tables と除外指定に従います。テーブルリストが指定されていない場合は、ステップ 2 で候補を検出し、ステップ 5 の前に対象テーブルのセットと件数をユーザーに承認してもらってから、その選択を seedTables として固定します。このスタンドアロンの検出パスでは、ローカルマニフェストがない場合は検証済みメタデータに照らして検証します。検出結果そのものを承認として扱ってはいけません。廃止が保留中の候補は常に除外します。その状態が不明な場合は、マニフェストを承認として扱わず、確認してください。読み取り専用のフォールバック検出は、環境へのシード投入を許可するものではありません。

呼び出し中は seedTables の許可リストを固定します。その後のすべての選択、バッチ、メディアジョブ、再開操作は、このリストの範囲内に留める必要があります。除外されたテーブルを対象にするために .datamodel-manifest.json やアプリプランを編集してはいけません。スコープを拡大するには、承認を管理するゲートに戻る必要があります。

--plan-only または計画フェーズの引き継ぎでは、提示されたテーブルスコープを読み取り専用の確認に使用し、ステップ 5 の前に、提案された件数、依存関係の要件、メディアポリシーを返します。計画の承認は挿入の承認ではありません。このパスでは、メディアファイルを生成したり、レコードを挿入/更新/アップロードしたり、アプリプラン、マニフェスト、シードデータ履歴を変更したりしてはいけません。

プロトタイプのシードを再利用する

--from-seed は、モックプロトタイプを Dataverse に変換した後、/prototype-to-real-app が使用します。このモードでは、新しい行を生成する前に、既存のプロトタイプのシードファイルを優先します。

src/generated/services/*/*.seed.json
src/generated/services/*.seed.json

.datamodel-manifest.json を使用して、seedTables のオブジェクトだけを Dataverse ペイロードにマッピングします。プロトタイプのシードファイルによって承認済みのテーブルセットを拡大してはいけません。

  • 実際のマニフェスト列の値だけを保持します。
  • ルックアップ参照は、マニフェストに記載された正確な <schemaName>@odata.bind キーに変換します。
  • マニフェストに記載された選択肢の整数値を保持します。ラベルから値を作り出してはいけません。
  • Dataverse 列に対応しない、ローカル専用のプロトタイプフィールドはスキップします。
  • 依存関係の階層順で挿入します。

シードファイルを安全にマッピングできない場合は、そのテーブルに対して生成したコンテキストに即したサンプル行にフォールバックし、概要に DONE_WITH_CONCERNS を記録します。--from-seed は優先設定であり、不正なデータの挿入を許可するものではありません。


Step 1 — プロジェクトと認証を確認する

各シェル呼び出しで、解決済みの working_dir からアプリローカルのコマンドを実行します。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then
  echo "BLOCKED: working_dir is not an initialized app" >&2
  exit 1
fi
environment_id="$(node -p "require('./power.config.json').environmentId || ''")" || exit 1
if [ -z "$environment_id" ]; then
  printf '%s\n' 'ERROR: selected app has no environmentId' >&2
  exit 1
fi
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$environment_id" --no-cache --require-tenant

後続のスクリプト呼び出しのために、環境 URL、環境 ID、テナント IDを取得し、選択したアプリおよび指定された所有者コンテキストと一致することを確認します。識別情報が不完全または競合している場合は、読み取り専用の限定的なリカバリー後に NEEDS_CONTEXT を返します。安全フラグを削除したり、別の環境を選択したり、リゾルバーの出力を保存してリカバリーしたりしないでください。

後続の Dataverse の読み取り、バッチ、PATCH、メディアのアップロード、トークンの更新、再試行はすべて、同じ環境 URL とテナント ID にバインドします。dataverse-request.js を呼び出すたびに、--tenant-id '<tenantId-from-resolve-environment>' を明示的に渡してください。新しいシェル呼び出しのたびに、検証済みの Step 1 の値を再度指定します。以前のシェルのエクスポート、チャレンジの検出、アクティブな Azure CLI テナントに依存しないでください。テナントコンテキストが不足または競合している場合は、呼び出しの前に NEEDS_CONTEXT を返します。

Azure CLI の認証を確認します(スクリプトには Azure CLI トークンが必要です)。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
az account show --query "user.name" -o tsv

空の場合は az login を実行するよう案内し、停止します。

Step 2 — テーブルを検出する

テレメトリチェックポイント:discover_dataverse_tables

Step 2a — Path A:.datamodel-manifest.json を読み取る(推奨)
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
test -f .datamodel-manifest.json

存在する場合は JSON を解析します。検証済みのアプリインベントリには、logicalName、displayName、status(new / extended / reused)、および columns が含まれています。これが推奨パスです -- 高速で、API 呼び出しもありません。スコープ指定された呼び出しでは、テーブルごとのメタデータや件数を問い合わせる前に、検証済みの seedTables エントリのみを使用します。単独での検出では、候補リストから廃止予定のテーブルを除外します。

Step 2b はスキップします。

Step 2b — Path B:OData をクエリする(フォールバック)

オーケストレーションされた呼び出しで .datamodel-manifest.json が見つからない場合は、検証済みインベントリの復旧を所有者に求めるため、BLOCKED を返します。検出範囲を広げたり、スキーマ情報を捏造したりしないでください。テーブルの許可リストが明示された単独のリクエストでは、それらの論理名についてのみメタデータを取得します。次の広範な検出は、テーブルリストが指定されていない単独のリクエストで、承認を求める候補を提示するためのものです。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "EntityDefinitions?\$select=LogicalName,DisplayName,EntitySetName&\$filter=IsCustomEntity eq true" \
  --tenant-id '<tenantId-from-resolve-environment>'

プロジェクトで使用している各候補(または明示的にスコープ指定された各テーブル)について、カスタム列を取得します。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "EntityDefinitions(LogicalName='<table>')/Attributes?\$select=LogicalName,DisplayName,AttributeType,RequiredLevel&\$filter=IsCustomAttribute eq true" \
  --tenant-id '<tenantId-from-resolve-environment>'

マニフェストと同じ { logicalName, displayName, columns: [...] } 形式を作成します。

ステップ 3 — テーブルを選択して件数を確認

検証済みのシード許可リストのみを評価します。再利用するテーブルも、そのリストに明示的に含まれている場合に限ります。単独で検出を行う場合は、廃止予定ではない候補のみを使用し、挿入前に選択の承認を得てください。 以下の追加の共有環境確認を得ずに、標準システムテーブル(例:contact、account、systemuser)をシードしないでください。

シード前の行数確認(必須 — 行を生成する前に、すべてのテーブルで実行):

対象となる各テーブルについて、マニフェストから確認済みのエンティティセット名を使って現在のレコード数をクエリするか、ステップ 5a のようにメタデータからその名前を取得します。 論理名に s を付けて名前を導出しないでください。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "<entitySetName>?\$top=5&\$select=<primaryKeyColumn>" \
  --tenant-id '<tenantId-from-resolve-environment>'

返された value 配列の行数を数えます。

既存レコード数アクション
≥5このテーブルを完全にスキップします。 ログに記録します:↷ <table> (≥5 records exist, skipping)。行を生成または挿入しないでください。
<5クラスごとの目標件数に達するよう、新しい行をシードします。既存レコードがある場合(例:2 件)は、不足分のみ(例:目標の 5 件に達するまで、さらに 3 件)を生成します。

選択済みでシード対象となるすべてのテーブルにすでに ≥5 件のレコードがある場合は、承認済みのシード対象にシードが必要なものはないと報告し、終了してください。

クラスごとのテーブル件数(生成前にマニフェストの情報を基に各テーブルを分類します。参照テーブルには大量のデータが不要で、トランザクションテーブルには状態のばらつきが必要なため、一律の 5 よりこちらを優先します):

クラス判定基準デフォルト件数理由
参照status / state 列がなく、列が説明的(名前、住所、電話番号)。多くの場合 Tier 0。3店舗、顧客、拠点、製品。少数で安定したセットです。
中間テーブル2 つ以上のルックアップがあり、その他に意味のある列がない。多くの場合 Tier 1。親の件数 × 3、最大 9 件店舗と割り当て、プロジェクトとユーザー。結合全体にわたるデータが必要です。
トランザクションstatus / state / phase の選択列と日付列(createdon、submittedat、completedat)がある。5監査、検査、注文、チケット。タイルに情報を表示するには、状態にばらつきが必要です。
詳細 / 明細トランザクションの親へのルックアップがあり、独自の状態列がない。親 1 件あたり 2~3 件監査ゾーン、注文明細、検査結果。
問題 / 指摘事項トランザクションの親へのルックアップがあり、status(Open / Resolved)と重大度(Critical / Moderate / Minor)がある。トランザクションの親 1 件あたり 3~4 件問題、不具合、所見。重大度とステータスにばらつきを持たせます(ステップ 4a を参照)。
証拠 / 添付ファイルFile / Image 列と、問題または検査へのルックアップがある。親のおよそ 30% あたり 1 件写真による証拠、文書のアップロード。デフォルトではメタデータ行をシードします。ファイル / 画像のバイトデータをシードするのは、brand/media-policy.md またはユーザーのリクエストでサンプルメディアが必要とされている場合のみです。
ログ / イベント / 監査証跡eventtype 列挙型、タイムスタンプ、実行者へのルックアップを持つ追記専用。トランザクションの親 1 件あたり 2 件監査ログイベント、アクティビティストリーム。親ごとに少なくとも 2 種類のイベントを混在させます。
上書き / 承認トランザクションの親へのルックアップと、ステータス(Pending / Approved / Rejected)がある。親のおよそ 20% あたり 1 件上書きリクエスト、承認キュー。キュータブに内容を表示するため、Pending の行を少なくとも 1 件含めます。

件数は意図的に最小限にしています。目標はデモ用データセットを作ることではなく、すべての画面に表示するものを用意することです。

1 行の要約を出力して続行します:

→ Seeding <total> records into <N> tables (coverage-first; counts auto-tuned per class).

ステップ 3b — 挿入順序を決定する

選択したテーブルについて、ルックアップ列から依存関係グラフを構築します。

  1. 外部へのルックアップがないテーブル → ティア 0(最初に挿入)
  2. ティア 0 のみへのルックアップを持つテーブル → ティア 1
  3. 選択したすべてのテーブルがティアに分類されるまで続行します

選択したテーブルが未選択の親を参照している場合、そのルックアップが承認済み機能の範囲内であれば、境界付き読み取りを通じて検証済みの既存の親レコードを再利用します。ルックアップの親を読み取ることは、それを挿入/更新する権限ではありません。適切なレコードが存在しない場合は、シードスコープを拡張するか、オプションのルックアップを明示的に省略するために、オーナーに NEEDS_CONTEXT を返します(またはスタンドアロンで問い合わせます)。親を seedTables に自動追加したり、廃止予定の親を作成したり、必須のルックアップを省略したりしないでください。廃止予定のルックアップ対象は、計画が調整されるまでその依存シードをブロックします。

ステップ 4 — サンプルデータの生成 + プレビュー

テレメトリチェックポイント: generate_and_review_sample_records

ステップ 4a — コンテキストに応じた行を生成する

選択した各テーブルについて、N 行を生成します。値を列名 + 型に一致させます。

列の型生成アプローチ
文字列列名のセマンティクスに一致させます。*name、*title → 要件ブリーフのコンテキストに基づく現実的な名前。*email → [email protected]。*phone → (555) 123-NNNN。*address → 現実的な通り + 都市。それ以外: コンテキストに適した短いテキスト。
メモ(複数行テキスト)列名に関連する 1〜3 文(例: *notes、*description)。
整数 / 小数 / 通貨列名に基づく妥当な範囲。*amount、*price → 現実的なドル額。*count、*quantity → 小さな整数(1〜100)。
DateTime / DateOnly過去 30 日から今後 14 日にわたる最近の ISO 日付。行ごとに変化させます。
ブール値true/false を混在させます(is_active 形式の名前では true 寄りの約 70/30)。
選択肢(ピックリスト)最初にオプションをクエリし(ステップ 4b)、有効な整数値から選択します。
複数選択の選択肢オプションセットから行ごとに 1〜3 個の有効な値を選択します。
ルックアップ検証済みの既存の親、または承認済みシードスコープ内で挿入された親を参照します。ライブの親 GUID を追跡します。子を満たすためだけに未承認の親をシードしないでください。
画像 / ファイルデフォルト: スキップ — null のままにします。メディアシードが有効で、その列がビジネスデータ(製品画像、検査証拠、NC 証明)である場合は、assets/sample-* から生成済み/合成のローカルファイルを使用し、来歴を記録します。装飾用の UI ヒーローアセットを Dataverse にアップロードしないでください。

メディアシードポリシー(ビジネスデータのみ、必要な場合のみ):

  • デフォルト: バイナリメディアをシードしません。メタデータ行をシードし、画面計画またはユーザーリクエストが表示可能なサンプルメディアを必要としない限り、画像/ファイル列は null のままにします。
  • Dataverse の画像/ファイルは、ユーザーがリスト/詳細画面で確認するレコードに属する画像(製品写真、証拠、添付ファイル、署名、問題証明)である場合にのみシードします。ホームのヒーロー、スプラッシュ、アプリアイコン、空状態のアート、装飾用の詳細背景はシードしないでください。
  • ロゴ、実際の製品ラベル、顔、透かし、競合他社のブランドを含まない、生成済み/合成アセットを優先します。ユーザーが承認済みアセットを提供する場合は、それを使用し、そのソースを記録します。
  • CDN URL は、明示的な URL/テキスト列(例: imageurl、photourl)でのみ有効です。CDN URL をファイル/画像列に入れないでください。
  • Dataverse の画像列は、行ペイロードまたは生成されたサービスシェイプ内で base64 を受け取ります。Dataverse のファイル列は、メタデータ行が存在した後に 2 回目のアップロード手順を必要とします。
  • 製品/チャネルアプリでは、製品リスト/詳細画面が視覚的な場合、製品画像はコアサンプルデータですが、上限があります。代表的なサブセットのみを生成してアップロードし、残りにはローカルプレースホルダーまたは null の画像フィールドを使用します。
  • assets/images/asset-manifest.json または assets/sample-media/asset-manifest.json を、ファイル、目的、ソース/ライセンス、安全性に関する注記とともに維持します。

メディア量の上限(ハード):

  • 製品/カタログテーブル: デフォルトでは最大 min(6, レコード数) 件のレコードに対して画像をアップロードします。レコードがカテゴリベースの場合は、上限に達するまでカテゴリごとに 1~2 件を選択します。残りのすべてのレコードは、ローカルのプレースホルダーサムネイルまたは空状態のフォールバックに依存します。
  • エビデンス/添付ファイルテーブル: 最大 親レコードの 30% のサンプルファイルをアップロードし、テーブルごとに合計 5 ファイルを上限とします。メタデータ行はファイルバイトなしでも存在できます。
  • ユーザー/アバター/機器/サイト画像: ユーザーが明示的により大きなビジュアルデモを求めない限り、テーブルごとに最大 3 件アップロードします。
  • ユーザーの明示的な承認がない限り、1 回の /add-sample-data 実行で 生成されるメディアファイルの合計が 10 件を超えないようにしてください。
  • 計算されたサンプル行数がメディアの上限を超える場合は、量よりも多様なカバレッジを優先してください: 主要製品 1 件、副次製品 1 件、エッジ/ステータスの例 1 件、その後はプレースホルダーとします。

サンプル画像の挿入方法:

  1. まず通常のレコード本体 (名前、参照フィールド、ステータスなど) を生成します。
  2. Image 列の場合、生成されたモデル/サービスがその列に base64 を期待する場合に限り、create/PATCH ボディにコンパクトな base64 ペイロードを添付します。モバイルのサムネイルに収まる程度の小さな画像にしてください。
  3. File 列の場合、create ボディにバイト/base64/URL を入れないでください。まずメタデータ行を挿入し、ステップ 5 の BATCH-RECORDS 結果から GUID を取得してから、ステップ 5d で (recordId, columnName) に生成したファイルをアップロードします。
  4. メディアの上限に達したら停止します。残りのレコードは Image/File 列を null のままにし、アプリ UI ではローカルのプレースホルダーを使用します。
  5. File 列用のアップロードヘルパーが存在しない場合は、その列を null のままにして sample media skipped — upload helper missing と報告します。File/Image データを URL 文字列で偽装しないでください。

要件ブリーフからコンテキストを引き出します。 ユーザーはアプリの機能を説明しています (例: 「フィールド技術者向けの HVAC 点検アプリ」)。それを使ってデータに特色を持たせてください — ユーザーの業界で典型的な通りの名前を付けたサイト、適切な語彙のステータスなど。汎用的な Lorem Ipsum は失敗パターンです。

親ごとのファンアウト下限 (HARD)。 Tier K+ のすべての子テーブルについて、Tier K-1 の親行ごとに 少なくとも 1 行を生成してください。ただし、関係が明示的にオプションである場合 (RequiredLevel: None がマニフェストにあり、かつ列名が *audit*、*inspection*、*order* のような 1 対多を意味しない場合) を除きます。この下限がないと、ランダムな参照分布によって一部の親に子がゼロになり、親の詳細画面が空でレンダリングされます。具体的なルール: audit_zones を生成していて 5 件の監査がある場合、少なくとも 5 件のゾーン (監査ごとに 1 件) を生成し、その後、クラスごとの目標件数に達するまで監査ごとに 0~2 件を追加します。決して逆にしてはいけません — 合計 N 件を生成して、各行がどの親を選ぶかを偶然に任せないでください。

状態 / ステータスの分布 (トランザクション、課題、オーバーライドクラスでは HARD)。 テーブルに status / state / phase / severity / priority の選択列がある場合、行を少なくとも 2 つの異なる値に分散させてください — すべて Open にしたり、すべて InProgress にしたりしないでください。具体的なルール:

  • トランザクション (audit、inspection、order): 可能であれば、オプションセットから少なくとも 3 つのライフサイクル状態を混在させてください — 通常、初期状態 (Draft / InProgress) に 1 行、中間状態 (Submitted / PendingReview) に 1 行、残りを終端状態 (Signed / Completed / Closed) にします。状態が 2 つしかない場合は、約 60/40 で分割します。
  • 課題 / 指摘: 重大度とステータスを独立に混在させてください。3 つの重大度 × 2 つのステータスにまたがる 5 件の課題がある場合、各重大度が 1 件以上、かつ Open が 1 件以上、Resolved が 1 件以上になることを目指します。
  • オーバーライド / 承認: キューの駆動状態 (Pending) の行を少なくとも 1 件含め、キュー/受信トレイタブに内容が表示されるようにします。残りは Approved / Rejected に分散させます。
  • ログ / イベント: 親ごとに少なくとも 2 つの異なる eventtype 値 (例: Created + StatusChanged) を含めます。 日付の分布(トランザクション/ログのみ)。 テーブルに createdon / submittedat / completedat / eventtimestamp 列がある場合、今日と過去14日間に行を分散させます(すべて今日、またはすべて30日前にはしません)。分布:今日/昨日に約30%(「最近のアクティビティ」タイルに反映)、過去7日間に約50%、8~14日前に約20%です。参照テーブルと詳細テーブルの日付は、妥当な範囲で自由に設定できます。期間を分散させる必要があるのは、トランザクション/ログのみです。

シナリオの類型に応じたエッジケースの網羅(検出できる場合は必須)。 選択した Power Apps のシナリオ類型を使って、アプリの UI が対応をうたう各重要状態を、少なくとも1行で検証します。

  • 現場検査/監査:ブロック中または証拠不足の監査を1件、進行中の監査を1件、完了/署名済みの監査を1件。
  • 資産メンテナンス:期限超過/優先度の高い作業指示を1件、部品待ちの作業指示を1件、完了した作業指示を1件。
  • 在庫スキャン優先:差異のある品目を1件、在庫ゼロ/低在庫の品目を1件、解決済みの棚卸し/移動を1件。
  • 承認:承認受信トレイにある保留中の項目を1件、承認済みの項目を1件、却下/変更依頼済みの項目を1件。
  • CRM:関係性にリスクがある顧客を1件、フォローアップ予定の顧客を1件、良好/成約済みの顧客を1件。
  • 小売カタログ/注文:画像付き商品を1件、在庫僅少/入荷待ちの例を1件、複数明細のある注文を1件。
  • ケース管理:エスカレーション済み/SLA リスクのあるケースを1件、顧客からの回答待ちのケースを1件、解決済みのケースを1件。
  • オンボーディング/トレーニング:期限超過の必須モジュールを1件、進行中のモジュールを1件、完了/認定済みのモジュールを1件。
  • 経費/申請の受付:領収書不足の下書きを1件、承認待ちの申請を1件、承認済み/支払い済みの申請を1件。
  • 健康/ウェルネス/ケア:本日実施予定のケアタスクを1件、未実施/フォローアップ対象のタスクを1件、完了/順調な目標を1件。
ステップ 4b — 選択肢の値を確認する

選択したテーブルにあるすべての選択肢列について、行を生成する前にオプションセットを照会します。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "EntityDefinitions(LogicalName='<table>')/Attributes(LogicalName='<column>')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?\$expand=OptionSet" \
  --tenant-id '<tenantId-from-resolve-environment>'

応答に含まれる実際の Value 整数を使用します。100000000 のような値をハードコードしないでください。値は環境によって異なります。

ステップ 4c — ユーザーにプレビューを表示する

各テーブルについて、会話内に行のプレビューを Markdown テーブルで直接表示します。

### Job Site (cr3e9_jobsite) — 5 records

| Site Name | Address | Square Feet | Active |
|---|---|---|---|
| Westside Construction Site | 4521 Industrial Pkwy | 12500 | true |
| Downtown Office Building   | 188 Main St           |  3200 | true |
| Eastgate Warehouse         | 9047 Logistics Way    | 28000 | false |
| Riverside Retail Plaza     | 320 River Rd          |  6800 | true |
| North Hills Distribution   | 1612 Highland Ave     | 18900 | true |

ルックアップを含むテーブルでは、各子レコードが参照する親レコードも表示します。

cr3e9_inspection の行は、上記の SiteName を持つ cr3e9_jobsite レコードを参照します。

ステップ 4d — 挿入に進む

--plan-only の場合、または計画フェーズから引き継がれた場合は、プレビューを返してここで停止します。 それ以前の承認や、入力済みのマニフェストがあっても、この制限は変わりません。

正確なシードテーブルと件数のポリシー、およびメディア書き込みが、現在のスコープ内の引き継ぎ、または明示的な個別リクエストですでに承認されている場合に限り、追加の確認なしで進めます。それ以外の場合は、まずプレビューについて明示的な承認を得てください。行数によって重複するボリュームを防ぐことはできますが、それは同意を意味しません。キャンセルされた場合は停止します。依存関係や行がより広いスコープを必要とする場合は、オーケストレーションされたリーフ内で範囲を拡大するのではなく、オーナーに差し戻します。

ステップ 5 — サンプルデータを挿入する

テレメトリチェックポイント:insert_sample_records

開始前に表示する内容:

「→ 依存関係の階層順で、 個のテーブルに合計 件のレコードを挿入しています(各階層内では並列処理、最大同時実行数は5件)…」

ステップ 3c の階層順に挿入します。各階層内では、スクリプトの BATCH-RECORDS モードを使い、テーブルと行の両方を並列処理します。Node プロセスは1つのみとし、Promise.all の同時実行数は最大5件に制限します。階層をまたぐ処理は順次実行します(子レコードは、前の階層の応答から取得した親 GUID を必要とするためです)。

⚠️ 並列処理が適用されるのは、レコードの挿入のみです。 スキーマ操作(テーブル/列/リレーションシップの作成)は必ず順次実行してください。/add-dataverse のステップ 5 並行処理ルールを参照してください。レコード操作にはメタデータロックがありませんが、メタデータの書き込みにはあります。これらを混在させると、429 / MetadataLockHeldException が返されます。

ステップ 5a — エンティティセット名を取得する

各テーブルについて、その EntitySetName(URL パス名。通常は複数形です。例:cr3e9_jobsites)を取得します。.datamodel-manifest.json に含まれていればそこから読み取り、含まれていない場合は次のようにします。

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "EntityDefinitions(LogicalName='<table>')?\$select=EntitySetName" \
  --tenant-id '<tenantId-from-resolve-environment>'

結果をキャッシュします。

⚠️ すべてのルックアップについて、両側の EntitySetName を解決してください。 挿入先テーブルのエンティティセット名(BATCH-RECORDS の entitySet フィールド)だけでなく、@odata.bind の値(ステップ 5c)で参照するすべてのルックアップ対象についても必要です。エンティティセット名は論理名とは別のものです。Dataverse の複数形は不規則で、バージョン接尾辞はそのまま引き継がれます。間違いやすい例:cr3e9_inspectionv3 → cr3e9_inspectionv3s(cr3e9_inspections ではありません)、cr3e9_inquiry → cr3e9_inquiries、cr3e9_status → cr3e9_statuses。パスを <logicalName>s として決して組み立てず、必ず EntityDefinitions から読み取ってください。

ステップ 5b — ティアごとに順番に挿入し、同じティア内では並列に実行する

ティア 0 から N まで、各ティアについて次を行います。

バッチを構築または送信する前に、すべての対象論理名を seedTables および retiringTables と照合して再確認します。正確なエンティティセットを解決し、いずれかの挿入/更新が未承認または廃止対象のテーブルを対象としている場合は、提案されたバッチ全体を拒否します。メディアの PATCH/アップロードと各再試行の前にも同じチェックを適用します。スコープ外の操作はスコープエラーであり、そのまま続行するレコード失敗ではありません。

  1. 操作配列を構築します。 このティアに含まれるすべてのテーブルについて、各(entitySet, body)ペアを収集します。結果を行の識別情報に対応付けるために使う、一意の index をそれぞれに付与します。

    [
      { "index": 0, "entitySet": "cr3e9_jobsites", "body": { "cr3e9_sitename": "Westside Construction Site", "cr3e9_address": "4521 Industrial Pkwy", "cr3e9_squarefeet": 12500, "cr3e9_active": true } },
      { "index": 1, "entitySet": "cr3e9_jobsites", "body": { "cr3e9_sitename": "Downtown Office Building", "cr3e9_address": "188 Main St",          "cr3e9_squarefeet":  3200, "cr3e9_active": true } },
      { "index": 2, "entitySet": "cr3e9_inspectors", "body": { "cr3e9_fullname": "Jane Smith", "cr3e9_email": "[email protected]" } }
      // ... all rows for tables in this tier
    ]
    

追跡情報と結果を関連付けられるよう、サイドマップ { index → { table, rowSemantic } } を維持します。

  1. ティアごとに BATCH-RECORDS を 1 回実行します。 スクリプトが並行処理、再試行、GUID 抽出、適応型スロットリングを内部で処理します。

    cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
    node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> BATCH-RECORDS \
      "Tier <N>" \
      --operations '<json-from-step-1>' \
      --concurrency 5 \
      --solution '<solution-uniquename-from-memory-bank>' \
      --tenant-id '<tenantId-from-resolve-environment>'
    

出力は { "status": 200, "data": [{ "index": 0, "status": 204, "recordId": "<guid>" }, ...] } です。結果は入力インデックス順に並びます(並列実行でも順序は一定です)。

  1. 親 GUID を取得します。 レスポンス内で成功したすべての行について、recordId を行の識別情報に対応付けて保存します。ティア N+1 の @odata.bind の値には、このマップを使用します。

    挿入したレコードごとに 1 行出力します(出力が順番に並ぶよう、レスポンス配列を入力インデックス順に反復します)。

    → ✓ <table>: <primary-name-value> (<guid>)

  2. 失敗を処理します。 ティア内の操作のいずれかが非 2xx または error を返した場合、親の挿入に失敗した子行はスキップしますが、成功した行を対象に次のティアへ進みます。理由:ティア 1 を中断するとティア 2 以降が空になり、カバレッジ要件を満たせなくなります。スキップした各子行と、後続ティアへの影響をステップ 6 のまとめに記録してください。

ステップ 5c — ルックアップを使って子テーブルを挿入する(こちらも BATCH-RECORDS 経由)

Tier 1 以降のテーブルでは、前の階層で取得した親 GUID を参照する @odata.bind を使って、各行の本文を作成します。BATCH-RECORDS の呼び出し形式は同じです。

[
  {
    "index": 0,
    "entitySet": "cr3e9_inspections",
    "body": {
      "cr3e9_inspectionnumber": "INS-001",
      "cr3e9_status": 100000000,
      "[email protected]": "/cr3e9_jobsites(<parent-guid-from-tier-0>)"
    }
  }
]

続いて:

cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> BATCH-RECORDS \
  "Tier 1" \
  --operations '<json-with-bound-lookups>' \
  --concurrency 5 \
  --solution '<solution-uniquename-from-memory-bank>' \
  --tenant-id '<tenantId-from-resolve-environment>'

⚠️ ルックアップの書き込み構文(厳守 — 形式が間違っていると、null が黙って保存されるか、明示的に 404 が返されます):

  • @odata.bind の左側のプロパティ名は、PascalCase のナビゲーションプロパティです。例:cr3e9_Site(読み取り専用の _cr3e9_siteid_value ではありません)。
  • 値はエンティティセットのパスです:/<entitySetName>(<guid>)。先頭の / に注意してください。
  • <entitySetName> は LOOKUP の参照先テーブルの EntitySetName であり、Step 5a で取得します。列の論理名に s を付けたものではありません。 <logicalName>s として構築すると、行が存在していても Entity '<targetTable>' With Id = <guid> Does Not Exist が返されます。これは、Dataverse が誤ったエンティティセットを正しいテーブルに解決できないためです。バージョン付きテーブル(cr3e9_inspectionv3 → cr3e9_inspectionv3s)と不規則な複数形(cr3e9_inquiry → cr3e9_inquiries)がよくある落とし穴です。
  • <guid> は、現在のプロセスで実行したライブクエリから取得する必要があります。親の BATCH-RECORDS レスポンス(Step 5b/5c)、または再開時に親テーブルへ新たに GET した結果(Step 5f)のいずれかです。以前のセッションの stdout から GUID をコピーして貼り付けないでください。
  • 形式が間違っていると、関連付けが黙って破棄される(親 FK のないレコードが作成され、アプリに孤立した行が表示される)か、階層全体が 404 になります。標準的なパターンについては、references/dataverse-reference.md § Setting Lookups を参照してください。
ステップ 5d — レコード挿入後にサンプルメディアをアップロードする(有効な場合のみ)

このステップは、Step 4a で業務用 Image/File 列のメディアジョブを作成した場合にのみ実行します。装飾用 UI アセットに対しては、絶対に実行しないでください。

各メディアジョブの対象テーブルは、引き続き seedTables に含まれ、かつ retiringTables に含まれていない必要があります。以前に取得した GUID があっても、新たな対象として使用する許可にはなりません。

行の生成時に mediaJobs サイドカーを作成します。

[
  {
    "table": "cr3e9_product",
    "rowIndex": 2,
    "recordId": "<filled-after-BATCH-RECORDS>",
    "columnName": "cr3e9_productimage",
    "columnType": "Image",
    "filePath": "assets/sample-media/gatorade-aseptic.png",
    "fileName": "gatorade-aseptic.png",
    "purpose": "product photo"
  }
]

各階層の BATCH-RECORDS レスポンス後、インメモリの { index → recordId } マップから recordId を設定し、列の種類に応じてメディアをアップロードします。

  • Step 1 の環境 URL とテナント ID を、認証およびトークン更新経路を含め、すべてのメディアヘルパーに明示的に渡してください。dataverse-request.js 経由の Image PATCH 呼び出しにも、同じ --tenant-id 引数が必要です。 File アップロードヘルパーでそのテナントへのバインドを強制できない場合は、呼び出したり、暗黙の認証情報にフォールバックしたりしないでください。バイトデータは未設定のままにし、sample media skipped — tenant-bound upload helper missing を報告して、メタデータ行を保持したままメディアに関する懸念事項を返してください。
  • Image 列: base64 値がすでに作成本文に含まれている場合は、メディアジョブを完了としてマークします。含まれていない場合は、エンティティセットとレコード GUID を使って、base64 文字列でレコードに PATCH します。画像は小さく、アプリで使うものにしてください。シードデータに数メガバイトの元画像をアップロードしないでください。
  • File 列: 行の作成後に、サポートされているアップロードヘルパーを呼び出します。アプリコードでは、生成されるサービスの形式は Service.upload(recordId, columnName, file, fileDisplayName?) です。CLI によるシードでは、同じ Dataverse のファイルアップロードフローを実行する専用ヘルパーを使用します。JSON 専用の dataverse-request.js BATCH-RECORDS モードは、バイナリアップロードの仕組みではありません。

重大な失敗時のルール: サンプル行のメディアアップロードに失敗しても、メタデータ行は保持し、Step 6 でメディアの失敗を記録して続行します。行を削除したり、スキーマ作成を再実行したりしないでください。アプリでは、プレースホルダー画像へのフォールバックを利用しながら、引き続きリストと詳細のデータを使用できるようにしてください。

以下の操作は絶対に行わないでください:

  • 列が実際に URL/Text 列でない限り、File/Image 列に CDN URL を設定しないでください。
  • base64 を File 列に詰め込まないでください。
  • UI のヒーロー画像、スプラッシュ画像、アイコンの各アセットを Dataverse にアップロードしないでください。
  • columnName を推測しないでください。.datamodel-manifest.json / field_bindings.file_columns にある正確な論理名を使用してください。
ステップ 5e — 結果の追跡と memory-bank

BATCH-RECORDS のレスポンスを追跡元として使用します。各階層のレスポンス配列について、次のように処理します。

  • 成功(status が 200~299、recordId が存在)→ メモリ内の { index → { table, primaryNameValue, recordId } } マップに追加します。
  • 失敗(status が 0/4xx/5xx で error がある)→ ステップ 6 の概要に記載するため、階層ごとの失敗リストに追加します。

すべての階層が完了した後(または厳格なデフォルト設定により停止した後)、以降の実行を冪等にするため、memory-bank.md の ## Seeded sample data に一括で書き込みます。実行ごとにテーブルあたり 1 行です。

## Seeded sample data

| Date | Table | Records inserted | First GUID | Last GUID |
|---|---|---|---|---|
| <ISO> | cr3e9_jobsite | 5 | <guid1> | <guid5> |

階層ごとではなく、実行後に 1 回の Edit 呼び出しですべての行を書き込みます。これにより、反復中のファイル書き込み競合を避け、監査ログをアトミックに保てます。

ステップ 5f — 失敗した階層からのリカバリー/再開

階層の途中で失敗し、再試行が必要な場合は、前回の実行の標準出力から親 GUID をハードコードした seed-resume.js を独自に作成しないでください。 この方法は Entity '<table>' With Id = <guid> Does Not Exist という 404 の最大の原因です。理由は、(a)前回の実行で出力された親行が実際にコミットされていない可能性があり、(b)再作成されたテーブルの GUID はすぐに古くなるためです。

安全な再開方法は次のとおりです。

再開前に、現在承認されている seedTables と廃止対象の除外を再確認します。以前の memory-bank の成功記録やシードファイルがあっても、現在のスコープから除外されたテーブルの使用は認められません。廃止対象のテーブルは再試行しないでください。

  1. 安定したビジネスキーで親 GUID を再クエリします。 失敗した階層の @odata.bind 値で参照されているすべての親テーブルについて、行の自然識別子(名前、テールナンバー、コードなど、シード時に主名として使用した値)でフィルターした GET を新たに実行します。例:

    cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
    node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
      "<parentEntitySet>?\$select=<parentIdColumn>,<naturalKey>&\$filter=startswith(<naturalKey>,'<seed prefix>')&\$top=50" \
      --tenant-id '<tenantId-from-resolve-environment>'
    

    レスポンスから新しい { naturalKey → guid } マップを作成します。

  2. ルックアップ対象ごとに EntitySetName を再クエリします(ステップ 5a)。テーブルの EntitySetName は変わらないものの、キャッシュファイルが別のプロジェクトのものである可能性があるため、前のセッションのキャッシュを信頼しないでください。

  3. 親のクエリ結果が予想より少ない場合は、停止します。 不完全なマップで続行しないでください。件数をユーザーに提示します。

    ⛔ 再開を中止しました:<table> 内の親行は <N> 件を想定していましたが、<K> 件見つかりました。Tier 0 から /add-sample-data を再実行してください(前回のセッションの GUID を信頼しないでください)。

  4. 再クエリした GUID と EntitySetName を operations 配列に反映し、失敗した階層を通常のステップ 5b/5c の BATCH-RECORDS 呼び出しとして再実行します。--solution フラグ、検証済みのステップ 1 の ID から取得した明示的な --tenant-id、および並行処理のルールを維持してください。復旧のためにテナントを切り替えないでください。

  5. 今回の再開レスポンスでシードされた、新しいメモリ内の { index → recordId } マップを使って、後続の階層へ進みます。

現時点で --resume フラグがない理由: 厳格なデフォルトの失敗動作(階層を停止し、失敗を提示してユーザーに再実行してもらう)と、上記のライブクエリのルールを組み合わせたものが再開方法です。フラグを設けると、スクリプトが既存のデータを自動的に特定できるかのような誤解を招きますが、部分的なコミットや同時編集があるため、キャッシュは信頼できません。リカバリーの判断はユーザーが行います。エージェントの役割は、状態を保持する独自の再開ヘルパーを作成するのではなく、ライブクエリのパターンに従うことです。

ステップ 6 — 概要
✅ Sample data seeded
─────────────────────────────────────────────
Environment   : <envUrl>
Solution      : <solution>
Seed scope    : <approved targets; excluded/retiring targets>
Tables seeded : <list with counts, e.g. cr3e9_jobsite (5), cr3e9_inspection (5)>
Total records : <N>
Failures      : <K> (see list below if K > 0)

Next steps:
  npm run dev          # Open the app — home screen now shows real data
  /preview-screens     # Generate static HTML preview with sample data
─────────────────────────────────────────────

失敗したレコードがある場合は、エラーメッセージを含む失敗のサブテーブルを出力し、ユーザーが原因を特定できるようにします。

部分的な結果には、成功ではなく懸念を示すステータスを返します。シードされていないテーブルや除外されたテーブルが正常に入力されたとは決して説明しないでください。シード処理によってプランのスキーマが変更されたり、.datamodel-manifest.json から移行中のエントリーが削除されたりすることはありません。

厳守ルール

  • シードの許可リスト内のみを対象とします。 廃止済み/未承認のテーブルは、マニフェストに含まれている場合やファンアウト先で必要な場合でも、常に対象外です。行数によるスキップと標準システムテーブルの確認ルールを守ってください。カバレッジ目標を理由にシードの対象範囲を広げてはいけません。
  • 親ごとのファンアウト下限 — Tier K-1 の各親に対し、Tier K に少なくとも 1 件の子を作成します(リレーションシップが必須、または 1 対多を意味する場合)。ランダムなルックアップの分布では親が孤立し、親詳細画面が機能しなくなります。子行は、親ごとに生成してください。親をランダムに選ぶフラットなバッチとして生成してはいけません。
  • トランザクション、課題、上書き、ログの各テーブルにおける状態/ステータスの分布 — 少なくとも 2 種類の異なる値を組み合わせてください。すべてをOpen、InProgress、またはPendingにしてはいけません。クラスごとの目標については Step 4a を参照してください。
  • トランザクション/ログテーブルの日付の分布 — 今日から過去 14 日間に分散させ、1 日に集中させてはいけません。目安は、最近が約 30%、先週が 50%、それより前が 20%です。
  • 実際の挿入にはBATCH-RECORDSモードを使用します — Node プロセスは 1 つとし、Tier 内は並列で処理し、結果の順序を保ち、429 に対して同時実行数を自動調整します。行ごとにnode dataverse-request.js POST ...を実行してはいけません。コールドスタートごとに約 150~300 ミリ秒かかります。バッチモードの目的は、そのコストをまとめて償却することです。
  • Tier 間は常に逐次処理、Tier 内は常に並列処理にします。 子には親の GUID が必要ですが、同じ Tier の行は互いに独立しています。これを混同すると、並列にしすぎて孤立したルックアップが作成されるか、逐次にしすぎて時間を無駄にします。
  • 同時実行数の上限は 5です(BATCH-RECORDS のデフォルト)。最初の 429 でスクリプトは自動的に 3 へ下げます。環境のサービス保護上限を測定して検証済みでない限り、--concurrencyをこれより大きく設定しないでください。
  • 並列処理を適用するのはレコードの挿入のみです。 スキーマ操作(EntityDefinitions、Attributes、RelationshipDefinitionsへの POST)は、Dataverse のメタデータロックのため、必ず逐次処理にしてください。既存の/add-dataverse Step 5 の同時実行ルールに変更はありません。
  • 標準システムテーブル(contact、account、incidentなど)には、デフォルトでシードしないでください。環境内の他のアプリと共有されているためです。ユーザーが明示的に選択した場合は、確認メッセージを表示してください:「これらのレコードは、この環境内のすべてのアプリから参照できます。続行しますか?」
  • レコードが自分たちのソリューションに追加されるよう、常に--solutionを渡してください。
  • ルックアップには、PascalCase のナビゲーションプロパティ名と/entitySet(guid)形式の値を使った@odata.bindを使用してください。 それ以外の形式では、リレーションシップが通知なしに破棄されるか、400 エラーが発生するか、Entity '<target>' With Id = <guid> Does Not Existという 404 エラーが発生します。BATCH-RECORDS モードはリクエスト本文をそのまま渡します。@odata.bindの形式は検証しないため、呼び出し元の責任で正しく指定してください。
  • ルックアップ先の EntitySetName は推測せず、必ず取得してください。 <logicalName>sという推測は、バージョン付きテーブル(cr3e9_inspectionv3s)や不規則な複数形(cr3e9_inquiries、cr3e9_statuses)では誤りです。@odata.bindの値で参照するすべてのルックアップ先について、EntityDefinitions(Step 5a)から EntitySetName を必ず読み取ってください。
  • @odata.bindの GUID は、現在のプロセス内でのライブクエリから取得してください。以前のセッションの標準出力に含まれる GUID は使用しないでください。 再開時は、親を自然キーで再クエリしてください(Step 5e)。GUID を手作業でseed-resume.jsに貼り付けてはいけません。
  • 独自の再開スクリプトを作成してはいけません。 Tier が失敗した場合は、Step 5e に従ってください(再クエリし、失敗した Tier を通常の BATCH-RECORDS 呼び出しとして再実行します)。inspGuids = [...]をハードコードした.tmp/seed-resume.jsは、必ず 404 エラーになります。
  • Choice 列ではラベルではなく、オプションセットの実際の数値Valueを使用してください。 まずオプションセットをクエリしてください(Step 4b)。
  • 失敗時に自動ロールバックしてはいけません。 厳格デフォルト(対話型)では、Tier が失敗すると実行を停止します。自動/カバレッジ優先モードでは、孤立レコードをスキップして続行します。どちらの場合も、クリーンアップの判断はユーザーに委ねてください。行を自動的に DELETE してはいけません。

参考資料

コメント