Upsert を使用してレコードを作成または更新
Upsert
メッセージを使用して、データ統合のシナリオに含まれる複雑さを減らすことができます。 データを外部システムから Microsoft Dataverse に読み込むとき、大量データの統合の場合など、レコードが Dataverse に既に存在するかが分からない場合があります。 このような場合、Update
または Create
メッセージを使用する必要があるかどうかが分かりません。 適切な操作を実行する前に、そのレコードが存在するかどうかを決定するために、最初にそのレコードを取得する必要があります。 Upsert
メッセージを使用すると、この複雑さを軽減してデータをより効率的に Dataverse に読み込むことができます。
Upsert
の使用は、Create
の使用と比べると、パフォーマンスを低下させます。 レコードが存在しないことが確実な場合は、Create
を使用します。
注意
Upsert
で主キーの値を使用できますが、一般的な使用例はデータ統合シナリオであるため、通常は代替キーを使用することが予想されます。 詳細情報: レコードを参照する代替キーの使用
エラスティック テーブルの upsert
Upsert
のエラスティック テーブルの動作は、標準テーブルとは異なります。 エラスティック テーブルでは、レコードが既に存在するかどうかに応じて、Upsert
操作は Create
や Update
メッセージを呼び出しません。 Upsert
は、エンティティ内の変更を直接適用します。
- レコードが存在する場合: レコード内のすべてのデータがエンティティ内のデータによって上書きされます。
Update
イベントはありません。 - レコードが存在しない場合: 新しいレコードが作成されます。
Create
イベントはありません。
これは、イベントのビジネス ロジックを適用する場所に影響します。 新しいレコードは、Create
や Upsert
を使用して作成できます。 レコードは Update
や Upsert
のいずれかを使用して更新できます。 エラスティック テーブルの Create
や Update
に一貫してロジックを適用する必要がある場合は、そのロジックを Upsert
にも含める必要があります。 詳細情報: エラスティック テーブルにレコードを upsert する
標準テーブルの upsert プロセスを理解する
Upsert
メッセージはサーバーで処理されます。 SDK for .NET クラスは、サーバーで使用されるものと同じオブジェクトを使用します。 したがって、次の説明では、.NET 用 SDK クラスを使用して、UpsertRequest インスタンスがどのように処理され、 UpsertResponse インスタンスが返されるかを説明します。
次の手順では、標準テーブル用に UpsertRequest を受け取ったときの、サーバーでの処理ロジックについて説明します。
- UpsertRequest インスタンスは、
Create
またはUpdate
オペレーションの操作のデータを含む Entity インスタンスで設定された Target Property で届きます。- 通常、Entity インスタンスには、代替キーを使用してレコードを識別するために使用される値が設定された Entity.KeyAttributes Property があります。
- 存在する場合、Dataverse は、Target プロパティに設定された Entity インスタンスの Entity.Id プロパティを使用してレコードを検索しようとします。 それ以外の場合は、Entity.KeyAttributes Property の代替キー値が使用されます。
- レコードが存在する場合は、次の手順を実行します。
Target
Entity.Id に、見つかったレコードの主キーの値を設定します。Target
Entity.KeyAttributes コレクションで使用しているのと同じキーを使用するTarget
Entity.Attributes コレクションのデータをすべて削除します。Update
を呼び出します。- UpsertResponse.RecordCreated プロパティを
false
に設定します。 - UpsertResponse.Target の値として、
Target
エンティティから EntityReference を作成します。 - UpsertResponse を返します。
- レコードが存在しない場合は、次の手順を実行します。
Target
が Entity.Attributes コレクションに持たないTarget
Entity.KeyAttributes のデータをTarget
Entity.Attributes にすべてコピーします。Create
を呼び出します。- UpsertResponse.RecordCreated を
true
に設定します。 - EntityReference を
Target
エンティティから作成し、Create
操作のid
結果を UpsertResponse.Target の値として作成します。 - UpsertResponse を返します。
次の図は、UpsertRequest を受け取ったときのサーバー上のプロセスを示しています。
リクエスト作成のガイダンス
代替キーを使用してレコードを識別する場合、保存するデータを表す要求の一部に代替キー データを含めることは推奨されず、必要もありません。
Web API を使用していて .NET 用 SDK に慣れていない場合は、上記のサーバー側のプロセスに従うのを困難に感じる場合があります。 Web API には、説明と上の図で使用されている SDK オブジェクトと同じオブジェクト モデルはありませんが、下の表に示すようにデータをマッピングできます。
Web API | SDK | 説明設定 |
---|---|---|
URL のキー値 | Entity.KeyAttributes Property | レコードを識別する代替キー データが含まれています。 |
要求の本文 | Entity を UpsertRequest.Target Property に設定 | Create または Update に使用するデータが含まれています。 |
これらの要求は上記のようにサーバー上で処理されますが、次のように考えることができます。
- レコードが存在する場合: URL 内の代替キー値の要求本文のデータ セットは 削除 されるため、含める意味がありません。 これにより、代替キー値を使用してレコードを識別しているときに、レコードの代替キー値を更新できなくなります。 代替キーの値は、主キーまたは別の代替キー セットを使用して変更できます。
- レコードが存在しない場合: URL の代替キーに指定された値と_データが違っていても_、要求本文に設定されている代替キー値が新しいレコードの作成に使用されます。 要求本文に代替キー データがない場合は、URL の代替キー データが要求本文にコピーされます。 URL 内のキー値と対応する本文のキー値が一致しない状況を回避するには、その値を本文にまったく含めないことが最善策です。
Web API の使用
Web API を使用すると、Upsert
と Update
の両方のメッセージが、URL のキーによって識別される指定された EntitySet
リソースに対して http PATCH
を使用して開始されます。
Upsert
と Update
の違いは、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 で作成
この要求により、レコードが作成されます。
要求:
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 で更新
この要求は、上記のリクエスト要求によって作成されたレコードを更新します。
要求:
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
を返します。
要求:
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
を返して、これが更新操作であったことを示します。
要求:
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 の使用
クライアント アプリケーションは、Create
や Update
操作データがある Entity インスタンスで設定された Target Propertyを持つ UpsertRequest インスタンスを含む IOrganizationService.Execute Method を使用しています。 通常、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 分かかります。 個人データは収集されません (プライバシー ステートメント)。