Web API を使用して条件付き操作を実行する

Microsoft Dataverseでは、ETag と呼ばれる標準の HTTP リソースバージョン管理メカニズムを使用する条件付き操作がサポートされます。 Web API を使用して条件付き操作を使用して、レコードの取得を最適化し、アップサート操作を制限し、オプティミスティック コンカレンシーを適用して、他のユーザーによる変更の上書きを防ぎます。

ETag とリソースのバージョン管理

HTTP プロトコルは、リソースの特定のバージョンを識別するための エンティティ タグ (略して ETag ) を定義します。 ETag は、その正確な値は実装に依存する不透明な識別子です。 ETag 値は、強検証と弱検証の 2 種類で発生します。 厳密な検証は、対応する ETag 値が変更されていない場合、特定の URI で識別される一意のリソースがバイナリ レベルで同一であることを示します。 弱い検証では、リソース表現が同じ ETag 値に対して意味的に同等であることが保証されるだけです。

Dataverse では、すべてのエンティティ インスタンスに対して弱い検証用 @odata.etag プロパティが生成され、取得された各エンティティ レコードでこのプロパティが自動的に返されます。 詳細については、「 Web API を使用してテーブル行を取得する」を参照してください。

If-Match および If-None-Match ヘッダー

ETag 値を持つ If-Match ヘッダーと If-None-Match ヘッダーを使用して、リソースの現在のバージョンが最後に取得したバージョンと一致するか、以前のいずれかのバージョンと一致するか、またはどのバージョンとも一致しないかを確認します。 これらの比較は、条件付き操作のサポートの基礎を形成します。 Dataverse には、条件付き取得、オプティミスティック コンカレンシー、および限定されたアップサート操作をサポートする ETag が用意されています。

Warnung

クライアント コードでは、ETag の特定の値や、等しいか等しくないか以外の ETag 間の見かけ上の関係に意味を与えてはなりません。 たとえば、リソースのより新しいバージョンの ETag 値は、以前のバージョンの ETag 値より大きいとは限りません。 また、新しい ETag 値の生成に使用されるアルゴリズムは、サービスのリリース間で予告なく変更される可能性があります。

条件付き取得

Etag は、同じレコードに複数回アクセスするときにレコードの取得を最適化するのに役立ちます。 レコードを以前に取得した場合は、If-None-Match ヘッダーと共に ETag 値を渡して、前回取得時から変更がある場合のみデータを要求します。 データが変更された場合、要求は、要求の本文に最新のデータを含む 200 OK の HTTP 状態を返します。 データが変更されていない場合、要求は HTTP 状態コード 304 Not Modified を返して、レコードが変更されていないことを示します。

次のメッセージ ペアの例では、最後に取得してからデータが変更されておらず、Etag 値が 00000000-0000-0000-0000-000000000001 であったときに、W/"468026" が accountid と等しいアカウント レコードのデータを返します。

リクエスト:

GET [Organization URI]/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)?$select=accountcategorycode,accountnumber,creditonhold,createdon,numberofemployees,name,revenue   HTTP/1.1  
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  
If-None-Match: W/"468026"  

応答:

HTTP/1.1 304 Not Modified  
Content-Type: application/json; odata.metadata=minimal  
OData-Version: 4.0  

以降のセクションでは、条件付き取得の使用に関する制限について説明します。

テーブルでオプティミスティック コンカレンシーが有効になっている必要がある

次の Web API 要求を使用して、テーブルでオプティミスティック コンカレンシーが有効になっているかどうかを確認します。 オプティミスティック コンカレンシーが有効になっているテーブルでは EntityMetadata.IsOptimisticConcurrencyEnabled プロパティが true に設定されています。 このURLを使用して値を取得してください:

GET [Organization URI]/api/data/v9.2/EntityDefinitions(LogicalName='<Entity Logical Name>')?$select=IsOptimisticConcurrencyEnabled

次の例では、連絡先テーブルから値を取得します。

リクエスト:

GET [Organization URI]/api/data/v9.2/EntityDefinitions(LogicalName='contact')?$select=IsOptimisticConcurrencyEnabled  HTTP/1.1  
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  

応答:

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

{
   "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#EntityDefinitions(IsOptimisticConcurrencyEnabled)/$entity",
   "MetadataId": "608861bc-50a4-4c5f-a02c-21fe1943e2cf",
   "IsOptimisticConcurrencyEnabled": true
}

クエリに$expandを含めてはなりません

Etag は、取得している 1 つのレコードが変更されたかどうかのみ検出できます。 クエリで $expand を使用すると、より多くのレコードが返される可能性があり、それらのレコードのいずれかが変更されたかどうかを検出することはできません。 クエリに $expandが含まれている場合、要求は 304 Not Modifiedを返しません。

クエリに注釈を含めてはならない

GET要求に Prefer: odata.include-annotations ヘッダーを含めると、サーバーは304 Not Modifiedを返しません。 注釈の値は、関連するレコードの値を参照できます。 これらのレコードが変更された可能性があり、サーバーはこの変更を検出できないため、何も変更されていないことを示すのが正しくありません。

アップサート操作を制限する

アップサート操作では、レコードが存在しない場合にレコードが作成されます。それ以外の場合は、既存のレコードが更新されます。 ただし、ETag を使用してアップサートをさらに制限して、作成を防いだり、更新を防いだりすることはできます。

アップサートでの作成を禁止する

データを更新していて、レコードが意図的に削除された可能性がある場合は、レコードを再作成したくない場合があります。 この状態を回避するには、If-Match の値を持つ * ヘッダーをリクエストに追加します。

リクエスト:

PATCH [Organization URI]/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001) HTTP/1.1  
Content-Type: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  
If-Match: *  
  
{  
    "name": "Updated Sample Account ",  
    "creditonhold": true,  
    "address1_latitude": 47.639583,  
    "description": "This is the updated description of the sample account",  
    "revenue": 6000000,  
    "accountcategorycode": 2  
}  

応答:

サーバーでレコードが見つかると、ステータス 204 No Content の通常の応答が返されます。 サーバーがレコードを見つけられない場合は、状態 404 Not Foundで次の応答を受け取ります。

HTTP/1.1 404 Not Found  
OData-Version: 4.0  
Content-Type: application/json; odata.metadata=minimal  
  
{  
 "error": {  
  "code": "",  
  "message": "account With Id = 00000000-0000-0000-0000-000000000001 Does Not Exist"
 }  
}  

アップサートで更新を禁止する

データを挿入する場合、同じ id 値を持つレコードがシステムに既に存在している可能性があります。 この既存のレコードを更新したくない場合があります。 レコードの更新を防ぐには、値 "*" の If-None-Match ヘッダーをリクエストに追加します。

リクエスト:

PATCH [Organization URI]/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001) HTTP/1.1  
Content-Type: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  
If-None-Match: *  
  
{  
    "name": "Updated Sample Account ",  
    "creditonhold": true,  
    "address1_latitude": 47.639583,  
    "description": "This is the updated description of the sample account",  
    "revenue": 6000000,  
    "accountcategorycode": 2  
}  

応答:
レコードが見つからない場合は、ステータス 204 No Content の通常の応答を受け取ります。 レコードが見つかった場合は、ステータス 412 Precondition Failed の次の応答を受け取ります。

HTTP/1.1 412 Precondition Failed  
OData-Version: 4.0  
Content-Type: application/json; odata.metadata=minimal  
  
{  
  "error":{  
   "code":"",  
   "message":"A record with matching key values already exists."
  }  
}  

オプティミスティック コンカレンシーを適用する

オプティミスティック コンカレンシーを使用して、最後にレコードを取得してからレコードが変更されたかどうかを検出します。 更新または削除する予定のレコードが取得後にサーバーで変更された場合は、更新または削除の操作を完了したくない場合があります。 次のパターンを使用すると、この状況を検出し、レコードの最新バージョンを取得し、必要な条件を適用して、操作を再試行するかどうかを再評価できます。

削除時にオプティミスティック コンカレンシーを適用する

accountid ヘッダーで送信された ETag 値が現在の値と異なるため、If-Match の 00000000-0000-0000-0000-000000000001 を持つアカウントに対する次の削除要求は失敗します。 値が一致した場合は、204 No Content 状態を受け取ります。

リクエスト:

DELETE [Organization URI]/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001) HTTP/1.1  
If-Match: W/"470867"  
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  

応答:

HTTP/1.1 412 Precondition Failed  
Content-Type: application/json; odata.metadata=minimal  
OData-Version: 4.0  
  
{  
  "error":{  
    "code":"","message":"The version of the existing record doesn't match the RowVersion property provided." 
  }  
}  

更新時にオプティミスティック コンカレンシーを適用する

accountid ヘッダーで送信された ETag 値が現在の値と異なるため、00000000-0000-0000-0000-000000000001のIf-Matchを持つアカウントに対する次の更新要求は失敗します。 値が一致した場合は、204 No Content ステータスを受け取ります。

リクエスト:

PATCH [Organization URI]/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001) HTTP/1.1  
If-Match: W/"470867"  
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  
  
{"name":"Updated Account Name"}  

応答:

HTTP/1.1 412 Precondition Failed  
Content-Type: application/json; odata.metadata=minimal  
OData-Version: 4.0  
  
{  
  "error":{  
    "code":"","message":"The version of the existing record doesn't match the RowVersion property provided."
  }  
}  

こちらも参照ください

Web API の条件付き操作のサンプル (PowerShell)
Web API の条件付き操作のサンプル (C#)
Web API の条件付き操作のサンプル (クライアント側 JavaScript)
Web API を使用して演算を実行する
Http 要求を作成し、エラーを処理する