Effectuer des opérations conditionnelles à l’aide de l’API web

Microsoft Dataverse prend en charge les opérations conditionnelles qui utilisent le mécanisme de contrôle de version de ressources HTTP standard appelé ETags. Utilisez des opérations conditionnelles à l’aide de l’API Web pour optimiser les récupérations d’enregistrements, limiter les opérations upsert et appliquer une concurrence optimiste pour empêcher le remplacement des modifications apportées par d’autres utilisateurs.

ETags et contrôle de version des ressources

Le protocole HTTP définit une balise d’entité, ou ETag pour un court terme, pour identifier des versions spécifiques d’une ressource. Les ETags sont des identificateurs opaques dont les valeurs exactes dépendent de l’implémentation. Les valeurs ETag se produisent dans deux variétés : validation forte et faible. La validation forte indique qu’une ressource unique, identifiée par un URI spécifique, est identique au niveau binaire si sa valeur ETag correspondante est inchangée. La validation faible garantit uniquement que la représentation de ressource est sémantiquement équivalente pour la même valeur ETag.

Dataverse génère une propriété de validation faible @odata.etag pour chaque instance d’entité et retourne automatiquement cette propriété avec chaque enregistrement d’entité récupéré. Pour plus d’informations, consultez Récupérer une ligne de table à l’aide de l’API web.

en-têtes If-Match et If-None-Match

Utilisez les en-têtes If-Match et If-None-Match avec des valeurs ETag pour vérifier si la version actuelle d’une ressource correspond à celle que vous avez récupérée pour la dernière fois, correspond à une version précédente ou ne correspond à aucune version. Ces comparaisons constituent la base de la prise en charge des opérations conditionnelles. Dataverse fournit des ETags pour prendre en charge des récupérations conditionnelles, l'accès concurrentiel optimiste et des opérations upsert limitées.

Avertissement

Le code client ne doit pas donner de signification à la valeur spécifique d’un ETag, ni à toute relation apparente entre ETags au-delà de l’égalité ou de l’inégalité. Par exemple, une valeur ETag pour une version plus récente d’une ressource n’est pas garantie d’être supérieure à la valeur ETag d’une version antérieure. En outre, l’algorithme utilisé pour générer de nouvelles valeurs ETag peut changer sans préavis entre les versions d’un service.

Récupérations conditionnelles

Les etags vous aident à optimiser les récupérations d’enregistrements lorsque vous accédez au même enregistrement plusieurs fois. Si vous avez précédemment récupéré un enregistrement, transmettez la valeur ETag avec l’en-tête If-None-Match pour demander des données uniquement si cet enregistrement a changé depuis la dernière fois que vous l’avez récupéré. Si les données ont changé, la requête retourne un état HTTP contenant 200 OK les données les plus récentes dans le corps de la requête. Si les données ne sont pas modifiées, la requête retourne le code d’état HTTP 304 Not Modified pour indiquer que l’enregistrement n’est pas modifié.

L’exemple de paire de messages suivant retourne des données pour un enregistrement de compte avec la valeur accountid égale à 00000000-0000-0000-0000-000000000001 lorsque les données n’ont pas changé depuis la dernière fois que vous les avez récupérées et que la valeur Etag était W/"468026".

Requête :

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"  

Réponse:

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

Les sections suivantes décrivent les limitations relatives à l’utilisation des récupérations conditionnelles.

La table doit avoir l’accès concurrentiel optimiste activé

Vérifiez si une table est configurée pour utiliser la concurrence optimiste à l’aide de la requête d’API web suivante. Les tables dont la concurrence optimiste est activée ont la propriété EntityMetadata.IsOptimisticConcurrencyEnabled définie sur true. Utilisez cette URL pour récupérer la valeur :

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

Cet exemple récupère la valeur de la table de contacts :

Requête :

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  

Réponse:

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
}

La requête ne doit pas inclure $expand

L’Etag ne peut détecter que si l’enregistrement unique que vous récupérez a changé. Lorsque vous utilisez $expand dans votre requête, vous pouvez retourner davantage d’enregistrements et il n’est pas possible de détecter si l’un de ces enregistrements a été modifié. Si la requête inclut $expand, la requête ne retourne jamais 304 Not Modified.

La requête ne doit pas inclure d’annotations

Lorsque vous incluez l’en-tête Prefer: odata.include-annotations dans une demande GET, le serveur ne retourne jamais 304 Not Modified. Les valeurs des annotations peuvent faire référence à des valeurs provenant d’enregistrements associés. Ces enregistrements peuvent avoir changé et le serveur ne peut pas détecter cette modification. Il serait donc incorrect d’indiquer que rien n’a changé.

Limiter les opérations upsert

Une opération upsert crée un enregistrement s’il n’existe pas ; sinon, elle met à jour un enregistrement existant. Toutefois, vous pouvez utiliser des ETags pour restreindre davantage les opérations d’upsert afin d’empêcher les créations ou les mises à jour.

Éviter la création dans upsert

Si vous mettez à jour des données et qu’il est possible que l’enregistrement ait été supprimé intentionnellement, vous ne souhaiterez peut-être pas recréer l’enregistrement. Pour empêcher cette condition, ajoutez un If-Match en-tête à la demande avec la valeur *.

Requête :

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  
}  

Réponse:

Si le serveur trouve l’enregistrement, vous obtenez une réponse normale avec l’état 204 No Content. Si le serveur ne trouve pas l’enregistrement, vous obtenez la réponse suivante avec l’état 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"
 }  
}  

Éviter la mise à jour dans upsert

Si vous insérez des données, un enregistrement avec la même id valeur peut déjà exister dans le système. Vous ne souhaiterez peut-être pas mettre à jour cet enregistrement existant. Pour empêcher la mise à jour de l’enregistrement, ajoutez un en-tête If-None-Match à la requête avec la valeur « * ».

Requête :

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  
}  

Réponse:
Si l’enregistrement est introuvable, vous recevez une réponse normale avec l’état 204 No Content. Si l’enregistrement est trouvé, vous recevez la réponse suivante avec l’état 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."
  }  
}  

Appliquer la concurrence optimiste

Utilisez la concurrence optimiste pour détecter si un enregistrement a été modifié depuis la dernière fois que vous l’avez récupéré. Si l’enregistrement que vous envisagez de mettre à jour ou de supprimer a changé sur le serveur depuis que vous l’avez récupéré, vous ne souhaiterez peut-être pas terminer l’opération de mise à jour ou de suppression. En utilisant le modèle suivant, vous pouvez détecter cette situation, récupérer la version la plus récente de l’enregistrement et appliquer tous les critères nécessaires pour réévaluer s’il faut réessayer l’opération.

Appliquer l’accès concurrentiel optimiste sur la suppression

La demande de suppression suivante pour un compte avec accountid de 00000000-0000-0000-0000-000000000001 échoue, car la valeur ETag envoyée avec l’en-tête If-Match est différente de la valeur actuelle. Si la valeur correspondait, vous recevez un 204 No Content statut.

Requête :

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  

Réponse:

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." 
  }  
}  

Appliquer l’accès concurrentiel optimiste sur la mise à jour

La demande de mise à jour suivante pour un compte avec accountid de 00000000-0000-0000-0000-000000000001 échoue, car la valeur ETag envoyée avec l’en-tête If-Match est différente de la valeur actuelle. Si la valeur a correspondu, vous recevez un statut 204 No Content.

Requête :

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"}  

Réponse:

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."
  }  
}  

Voir aussi

Exemple d’opérations conditionnelles de l’API web (PowerShell)
Exemple d’opérations conditionnelles de l’API Web (C#)
Exemple d′opérations conditionnelles de l′API Web (Javascript côté client)
Effectuer des opérations à l’aide de l’API Web
Composer des demandes Http et gérer les erreurs