Utilisation de Upsert pour Créer ou Mettre à jour un enregistrement
Vous pouvez réduire la complexité des scénarios d’intégration de données en utilisant le message Upsert
. En chargeant des données dans Microsoft Dataverse à partir d’un système externe, par exemple avec un scénario d’intégration de données en bloc, vous pouvez ne pas savoir si un enregistrement existe déjà dans Dataverse. Dans ce cas, vous ne pouvez pas savoir si vous devez utiliser le message Update
ou Create
. Vous devez récupérer un enregistrement pour déterminer s’il existe avant d’effectuer l’opération appropriée. Vous pouvez réduire cette complexité et charger des données dans Dataverse plus efficacement en utilisant le message Upsert
.
Il y a une pénalité des performances à utiliser Upsert
par rapport à Create
. Si vous êtes certain que l’enregistrement n’existe pas, utilisez Create
.
Notes
Bien que vous puissiez utiliser des valeurs de clé primaire avec Upsert
, on s’attend généralement à ce que vous utilisiez des clés alternatives, car le cas d’utilisation courant concerne les scénarios d’intégration de données. Pour plus d’informations : Utilisation d’une clé secondaire pour référencer un enregistrement
Upsert d’une table élastique
Le comportement des tables élastiques pour Upsert
est différent des tables standard. Avec les tables élastiques, l’opération Upsert
n’appelle pas le message Create
ou Update
selon que l’enregistrement existe déjà ou non. Upsert
applique directement les changements dans l’entité.
- Si l’enregistrement existe : toutes les données de l’enregistrement sont écrasées par les données de l’entité. Il n’existe aucun événement
Update
. - Si l’enregistrement n’existe pas : un enregistrement est créé. Il n’existe aucun événement
Create
.
Cela a des implications sur l’endroit où vous appliquez la logique métier pour les événements. Un enregistrement peut être créé en utilisant Create
ou Upsert
. Un enregistrement peut être mis à jour en utilisant Update
ou Upsert
. Si vous devez appliquer une logique cohérente pour Create
ou Update
dans les tables élastiques, vous devez également inclure cette logique dans Upsert
. Plus d’informations : Faire un upsert d’un enregistrement dans une table élastique
Comprendre le processus d’upsert pour les tables standard
Les messages Upsert
sont traités sur le serveur. Les classes Kit de développement logiciel (SDK) pour .NET utilisent les mêmes objets que ceux utilisés sur le serveur. Par conséquent, l’explication suivante utilise le SDK pour les classes .NET pour décrire comment une instance UpsertRequest est traitée et l’instance UpsertResponse renvoyée.
Les étapes suivantes décrivent la logique de traitement sur le serveur lorsque UpsertRequest est reçu pour une table standard :
- L’instance UpsertRequest arrive avec l’instance Target Property définie avec une instance Entity contenant les données d’une opération
Create
ouUpdate
.- L’instance Entity aura généralement la Entity.KeyAttributes Property définie avec des valeurs utilisées pour identifier l’enregistrement à l’aide de clés secondaires.
- S’il existe, Dataverse va essayer de rechercher l’enregistrement en utilisant la propriété Entity.Id de l’instance Entity définie sur la propriété Target. Sinon, il utilise les valeurs clé secondaire à partir de Entity.KeyAttributes Property.
- Si l’enregistrement existe :
- Définissez le Entity.Id
Target
avec la valeur de la clé primaire de l’enregistrement trouvé. - Supprimez toutes les données de la collection
Target
Entity.Attributes qui utilisent les mêmes clés que celles utilisées dans la collectionTarget
Entity.KeyAttributes. - Appelez
Update
. - Définissez la propriété UpsertResponse.RecordCreated sur
false
. - Créez une EntityReference à partir de l’entité
Target
de la mise à jour comme valeur de UpsertResponse.Target. - Retournez UpsertResponse.
- Définissez le Entity.Id
- Si l’enregistrement n’existe pas :
- Copiez toutes les données de la
Target
Entity.KeyAttributes que laTarget
n’a pas déjà dans sa collection Entity.Attributes vers laTarget
Entity.Attributes. - Appelez
Create
. - Définissez la propriété UpsertResponse.RecordCreated sur
true
. - Créez une EntityReference à partir de l’entité
Target
. Le résultat de l’id
de l’opérationCreate
contient la valeur de UpsertResponse.Target. - Retournez UpsertResponse.
- Copiez toutes les données de la
Le diagramme suivant montre le processus sur le serveur quand la classe UpsertRequest est reçue.
Conseils pour la rédaction des demandes
Lorsque vous utilisez des clés secondaires pour identifier un enregistrement, il n’est ni recommandé ni nécessaire d’inclure les données de clé secondaire dans la partie de la demande qui représente les données à enregistrer.
Si vous utilisez l’API web et que vous débutez avec le SDK pour .NET, le processus côté serveur décrit ci-dessus peut être difficile à suivre. L’API web n’a pas le même modèle d’objet que les objets Kit de développement logiciel (SDK) utilisés dans la description et le diagramme ci-dessus, mais les données peuvent être mappées comme indiqué dans le tableau ci-dessous.
API Web | SDK | Description |
---|---|---|
Valeurs de clés dans l’URL | Entity.KeyAttributes Property | Contient les données clé secondaire pour identifier l’enregistrement. |
Corps de la demande | La Entity définie sur la UpsertRequest.Target Property | Contient les données à utiliser pour Create ou Update . |
Bien que ces requêtes soient traitées sur le serveur comme décrit ci-dessus, vous pouvez y penser de la manière suivante :
- Si l’enregistrement existe : le jeu de données dans le corps de la requête pour ces valeurs de clé secondaire dans l’URL sont supprimées, donc cela ne sert à rien de l’inclure. Cette pratique garantit que vous ne pouvez pas mettre à jour les valeurs de clé secondaire d’un enregistrement lorsque vous utilisez ces valeurs de clé secondaire pour l’identifier. Vous pouvez modifier les valeurs clé secondaire à l’aide de la clé primaire ou d’un ensemble différent de clés alternatives.
- Si l’enregistrement n’existe pas : toutes les valeurs de clé secondaire définies dans le corps de la requête sont utilisées pour créer l’enregistrement, même si les données sont différentes par rapport aux valeurs spécifiées par les clés secondaires dans l’URL. S’il n’y a pas de données de clé secondaire dans le corps de la requête, les données de clé secondaire de l’URL sont copiées dans le corps de la requête. Pour éviter une situation où les valeurs de clé dans l’URL et les valeurs de clé correspondantes dans le corps ne correspondent pas, il est préférable de ne pas les inclure du tout dans le corps.
Utilisation de l’API Web
Avec l’API web, les messages Upsert
et Update
sont tous deux lancés en utilisant PATCH
http contre une certaine ressource EntitySet
identifiée par les clés dans l’Url.
La différence entre Upsert
et Update
est défini par le fait que l’en-tête de la demande If-Match: *
est inclus. Si l’en-tête de demande If-Match: *
est inclus et qu’aucune ressource ne correspond aux valeurs de clé dans l’URL, la requête renvoie un code de statut 404 Not Found
. L’en-tête de la demande If-Match: *
garantit que la demande PATCH
est une opération Update
.
Si l’en-tête de la requête If-Match: *
n’est pas inclus, la demande PATCH
est traitée comme un Upsert
et un enregistrement est créé si aucun enregistrement correspondant aux clés de l’URL n’est trouvé. Cependant, contrairement au SDK, la réponse ne vous indique pas si un enregistrement a été créé. La réponse du statut est 204 No Content
dans les deux cas.
Si vous incluez un en-tête de demande Prefer: return=representation
, le système renvoie un statut 201 Created
pour Create
et un statut 200 OK
pour Update
. L’ajout de cet en-tête ajoute une opération Retrieve
supplémentaire, ce qui a un impact sur les performances. Si vous utilisez cette option, assurez-vous que l’option de requête $select
que vous ajoutez inclut uniquement la valeur de la clé primaire. Pour plus d′informations :
Avec une demande PATCH
que vous puissiez également inclure l’en-tête de la demande If-None-Match: *
pour bloquer une Update
si vous souhaitez uniquement créer des enregistrements. Pour plus d’informations, voir : Limiter les opérations upsert
Exemple de code API web
Les exemples suivants montrent des opérations Upsert
utilisant une table avec deux colonnes clé secondaire :
Créer avec Upsert
Cette demande crée un enregistrement.
Demande :
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" }
Réponse :
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)
Mettre à jour avec Upsert
Cette requête met à jour l’enregistrement créé par la requête ci-dessus.
Demande :
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" }
Réponse :
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)
Notes
La réponse est identique pour les opérations de création ou de mise à jour.
Créer avec un upsert et une préférence retour=représentation
Quand vous utilisez l’en-tête Prefer: return=representation
, vous pouvez obtenir un code de statut différent dans la réponse pour indiquer si l’enregistrement a été créé ou mis à jour.
La requête suivante crée un enregistrement et renvoie le statut 201 Created
.
Demande :
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" }
Réponse :
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"
}
Mettre à jour avec Upsert et return=representation preference
Cette requête met à jour l’enregistrement créé par la requête ci-dessus et renvoie le statut 200 OK
pour montrer qu’il s’agissait d’une opération de mise à jour.
Demande :
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" }
Réponse :
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"
}
Utilisation du Kit de développement logiciel (SDK) pour .NET
Votre application cliente utilise la IOrganizationService.Execute Method avec une instance UpsertRequest qui a Target Property défini avec une instance Entity contenant les données pour une opération Create
ou Update
. L’instance Entity aura généralement la Entity.KeyAttributes Property définie avec des valeurs utilisées pour identifier l’enregistrement à l’aide de clés secondaires.
La UpsertResponse.RecordCreated Property vous indique si l’enregistrement a été créé, et la UpsertResponse.Target contient une référence à l’enregistrement qui a été créé ou mis à jour.
Exemple de code Kit de développement logiciel (SDK) pour .NET
L’exemple Insérer ou mettre à jour un enregistrement à l’aide de Upsert de l’exemple ProductUpsertSample.cs contient la méthode ProcessUpsert
suivante pour appliquer le message UpsertRequest
du contenu d’un fichier XML pour créer des enregistrements ou mettre à jour des enregistrements existants.
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;
}
}
}
Voir aussi
Utiliser le suivi des modifications pour synchroniser les données avec les systèmes externes
Définition de clés secondaires pour la table
Utilisation d’une clé secondaire pour référencer un enregistrement
Notes
Pouvez-vous nous indiquer vos préférences de langue pour la documentation ? Répondez à un court questionnaire. (veuillez noter que ce questionnaire est en anglais)
Le questionnaire vous prendra environ sept minutes. Aucune donnée personnelle n’est collectée (déclaration de confidentialité).