Upsert を使用してレコードを作成または更新

Upsert メッセージを使用して、データ統合のシナリオに含まれる複雑さを減らすことができます。 データを外部システムから Microsoft Dataverse に読み込むとき、大量データの統合の場合など、レコードが Dataverse に既に存在するかが分からない場合があります。 このような場合、Update または Create メッセージを使用する必要があるかどうかが分かりません。 適切な操作を実行する前に、そのレコードが存在するかどうかを決定するために、最初にそのレコードを取得する必要があります。 Upsert メッセージを使用すると、この複雑さを軽減してデータをより効率的に Dataverse に読み込むことができます。

Upsert の使用は、Create の使用に比べて、パフォーマンス ペナルティがあります。 レコードが存在しないことが確実な場合は、Create を使用します。

注意

Upsert で主キーの値を使用できますが、一般的な使用例はデータ統合シナリオであるため、通常は代替キーを使用することが予想されます。 詳細情報: レコードを参照する代替キーの使用

Upsert プロセスの詳細

Upsert メッセージはサーバーで処理されます。 SDK for .NET クラスは、サーバーで使用されるものと同じオブジェクトを使用します。 したがって、次の説明では、SDK for .NET クラスを使用して、UpsertRequest インスタンスがどのように UpsertResponse インスタンスによって返されたものを処理するかを説明します。

次の手順では、UpsertRequest を受け取ったときの、サーバー上の処理ロジックについて説明します。

  1. UpsertRequest インスタンスは、Create または Update オペレーションの操作のデータを含む Entity インスタンスで設定された Target Property で届きます。
    • 通常、Entity インスタンスには、代替キーを使用してレコードを識別するために使用される値が設定された Entity.KeyAttributes Property があります。
  2. 存在する場合、Dataverse は、Target プロパティに設定された Entity インスタンスの Entity.Id プロパティを使用してレコードを検索しようとします。 それ以外の場合は、Entity.KeyAttributes Property から代替キーの値を使用します。
  3. レコードが存在する場合は、次の手順を実行します。
    1. Target Entity.Id に、見つかったレコードの主キーの値を設定します。
    2. Target Entity.KeyAttributes コレクションで使用している同じキーを持つ Target Entity.Attributes コレクションからデータを削除します。
    3. Update を呼び出します。
    4. UpsertResponse.RecordCreated プロパティを false に設定します。
    5. UpsertResponse.Target の値として、Target エンティティから EntityReference を作成します。
    6. UpsertResponse を返します。
  4. レコードが存在しない場合は、次の手順を実行します。
    1. Target がその Entity.Attributes コレクションで_まだ持っていない_ Target Entity.KeyAttributes からのデータを Target Entity.Attributes にコピーします。
    2. Create を呼び出します。
    3. UpsertResponse.RecordCreatedtrue に設定します。
    4. EntityReferenceTarget エンティティから作成し、Create 操作の id 結果を UpsertResponse.Target の値として作成します。
    5. UpsertResponse を返します。

次の図は、UpsertRequest を受け取ったときのサーバー上のプロセスを示しています。

upsert プロセス フロー

リクエスト作成のガイダンス

代替キーを使用してレコードを識別する場合、保存するデータを表す要求の部分に代替キー データを含めることは推奨されておらず、必要もありません。

Web API を使用していて、SDK for .NET に慣れていない場合は、上記のサーバー側のプロセスに従うのが難しい場合があります。 Web API には、説明と上の図で使用されている SDK オブジェクトと同じオブジェクト モデルはありませんが、下の表に示すようにデータをマッピングできます。

Web API SDK 説明設定
URL のキー値 Entity.KeyAttributes Property レコードを識別する代替キー データが含まれています。
要求の本文 EntityUpsertRequest.Target Property に設定 Create または Update に使用するデータが含まれています。

これらの要求は上記のようにサーバー上で処理されますが、次のように考えることができます。

  • レコードが存在する場合: URL の代替キーの値に対する要求の本文のデータ セットは、_削除済み_ですので、含めても意味がありません、となります。 これにより、代替キーの値を使用してレコードを識別しているときに、レコードの 代替キーの値を更新されないようにします。 代替キーの値は、主キーまたは別の代替キー セットを使用して変更できます。
  • レコードが存在しない場合: 要求の本文に設定された代替キーの値はすべて、URL の代替キーで指定された値より_データが違っても_、新しいレコードの作成に使用されます。 要求の本文に 代替キー データがない場合、URL の代替キー データが要求の本文にコピーされます。 URL のキーの値と本文の対応するキー値が一致しない状況を回避するには、それらを本文にまったく含めないことをお勧めします。

Web API の使用

Web API を使用すると、``UpsertUpdateの両方のメッセージが、URL のキーによって識別される指定されたEntitySetリソースに対して httpPATCH` を使用して開始されます。

UpsertUpdate の違いは、If-Match: * 要求ヘッダーが含まれているかどうかによって定義されます。 If-Match: * 要求ヘッダーが含まれていて、URL のキー値でリソースを識別できない場合、要求は 404 Not Found 状態コードを返します。 If-Match: * 要求ヘッダーは、PATCH 要求が Update 操作であることを保証します。

If-Match: * 要求ヘッダーが含まれていない場合、PATCH 要求は Upsert のように扱われ、URL のキーに一致するレコードが見つからない場合は新しいレコードが作成されます。 ただし、SDK とは異なり、応答ではレコードが作成されたかどうかはわかりません。 状態の応答はどちらの場合でも 204 No Content となります。

Prefer: return=representation 要求ヘッダーを含めると、システムは Create に対して 201 Created の状態を返し、Update に対して 200 OK の状態を返します。 これにより、追加の Retrieve 操作が追加されるため、パフォーマンスに影響します。 このオプションを使用する場合は、追加する $select クエリ オプションに主キー値のみが含まれていることを確認してください。 詳細情報:

PATCH 要求では、If-None-Match: * 要求ヘッダーを含めて、レコードを作成するだけの場合は Update をブロックすることもできます。 詳細: upsert 操作の制限

Web API サンプル コード

次の例は、2 つの代替キー列を持つテーブルを使用した Upsert 操作を示しています。

Upsert で作成

この要求により、レコードが作成されます。

Request

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2) HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: application/json

{ "example_name": "2:2" }

回答

HTTP/1.1 204 No Content
OData-Version: 4.0
OData-EntityId: [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2)

Upsert で更新

この要求は、上記のリクエスト要求によって作成されたレコードを更新します。

Request

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2) HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: application/json

{ "example_name": "2:2 Updated" }

回答

HTTP/1.1 204 No Content
OData-Version: 4.0
OData-EntityId: [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2)

注意

応答は、作成または更新操作で同じです。

Upsert および return=representation の基本設定で作成

Prefer: return=representation 要求を使用すると、応答で別の状態コードを取得して、レコードが作成されたか更新されたかを示すことができます。

次の要求は、新しいレコードを作成し、状態 201 Created を返します。

Request

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=3,example_key2=3)?$select=example_recordid HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Prefer: return=representation
Content-Type: application/json

{ "example_name": "3:3" }

回答

HTTP/1.1 201 Created
Content-Type: application/json; odata.metadata=minimal
ETag: W/"71004878"
Preference-Applied: return=representation
OData-Version: 4.0

{
  "@odata.context": "[Organization Uri]/api/data/v9.2/$metadata#example_records(example_recordid)/$entity",
  "@odata.etag": "W/\"71004878\"",
  "example_recordid": "ef0d112e-d70e-ed11-82e5-00224822577b"
}

Upsert および return=representation の基本設定で更新

この要求は、上記の要求によって作成されたレコードを更新し、状態 200 OK を返して、これが更新操作であったことを示します。

Request

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=3,example_key2=3)?$select=example_recordid HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Prefer: return=representation
Content-Type: application/json

{ "example_name": "3:3 Updated" }

回答

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
ETag: W/"71004880"
OData-Version: 4.0

{
  "@odata.context": "[Organization Uri]/api/data/v9.2/$metadata#example_records(example_recordid)/$entity",
  "@odata.etag": "W/\"71004880\"",
  "example_recordid": "ef0d112e-d70e-ed11-82e5-00224822577b"
}

SDK for .NET の使用

クライアント アプリケーションは IOrganizationService.Execute MethodUpsertRequest インスタンスと共に使用します。 それには、Create または Update のデータが含まれる Entity インスタンスと Target Property があります。 通常、Entity インスタンスには、代替キーを使用してレコードを識別するために使用される値が設定された Entity.KeyAttributes Property があります。

UpsertResponse.RecordCreated Property は、レコードが作成されたかどうかを示し、UpsertResponse.Target には、作成または更新されたレコードへの参照が含まれています。

SDK for .NET サンプル コード

Upsert でレコードを挿入する サンプルの SampleMethod.cs ファイルは、次の ProcessUpsert メソッドを含み、XML ファイルのコンテンツに UpsertRequest メッセージを適用して、新しいレコードの作成や既存レコードの更新を実行します。

public static void ProcessUpsert(CrmServiceClient service, String Filename)
{
    Console.WriteLine("Executing upsert operation.....");
    XmlTextReader tr = new XmlTextReader(Filename);
    XmlDocument xdoc = new XmlDocument();
    xdoc.Load(tr);
    XmlNodeList xnlNodes = xdoc.DocumentElement.SelectNodes("/products/product");

    foreach (XmlNode xndNode in xnlNodes)
    {
        String productCode = xndNode.SelectSingleNode("Code").InnerText;
        String productName = xndNode.SelectSingleNode("Name").InnerText;
        String productCategory = xndNode.SelectSingleNode("Category").InnerText;
        String productMake = xndNode.SelectSingleNode("Make").InnerText;

        //use alternate key for product
        Entity productToCreate = new Entity("sample_product", "sample_productcode", productCode);

        productToCreate["sample_name"] = productName;
        productToCreate["sample_category"] = productCategory;
        productToCreate["sample_make"] = productMake;
        var request = new UpsertRequest()
        {
            Target = productToCreate
        };

        try
        {
            // Execute UpsertRequest and obtain UpsertResponse.
            var response = (UpsertResponse)service.Execute(request);
            if (response.RecordCreated)
                Console.WriteLine("New record {0} is created!", productName);
            else
                Console.WriteLine("Existing record {0} is updated!", productName);
        }

        // Catch any service fault exceptions that Dataverse throws.
        catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
        {
            throw;
        }
    }
}

関連項目

変更の追跡を使用してデータを外部システムに同期
テーブルの代替キーを定義する
代替キーを使用してレコードを参照

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。