Partager via


Mettre à jour et supprimer des lignes de table à l’aide du SDK pour .NET

Cet article comprend des exemples utilisant à la fois des styles de programmation à liaison anticipée et à liaison tardive. Pour plus d’informations, voir : Programmation avec liaison tardive et anticipée à l’aide du SDK pour .NET

Chacun des exemples utilise une variable svc qui représente une instance d’une classe qui met en place les méthodes dans l’interface IOrganizationService. Pour plus d’informations sur les classes qui prennent en charge cette interface, consultez l’interface IOrganizationService.

Important

Lors de la mise à jour d’une ligne de tableau, n’incluez que les colonnes que vous modifiez. La simple mise à jour des colonnes d’une ligne de tableau que vous avez précédemment récupérée mettra à jour chaque colonne même si la valeur est inchangée. Cela peut entraîner des événements système qui peuvent déclencher une logique métier qui prévoit que les valeurs aient réellement changé. Cela peut également donner l’impression que les colonnes ont été mises à jour dans les données d’audit alors qu’elles n’ont en fait pas changé.

Vous devez créer une instance Entity, définissez l’attribut ID et toutes les valeurs d’attribut que vous modifiez, et utilisez cette instance d’entité pour mettre à jour la ligne de la table.

Note

La définition de colonne comprend une propriété RequiredLevel. Lorsque celui-ci est défini sur SystemRequired, vous ne pouvez pas définir ces colonnes sur une valeur nulle. Si vous tentez de le faire, vous obtiendrez le code d’erreur -2147220989 avec le message Attribute: <attribute name> cannot be set to NULL.

Plus d’information : Niveau d’exigence de la colonne (attribut)

Mise à jour de base

Les deux exemples ci-dessous utilisent la méthode IOrganizationService.Update pour définir les valeurs de colonne d’une ligne de table précédemment extraite.

Utilisez la propriété Entity.Id pour transférer la valeur de l’identificateur unique de la ligne extraite vers l’instance d’entité utilisée pour exécuter l’opération de mise à jour.

Note

Si vous essayez de mettre à jour une ligne sans valeur de clé primaire, vous obtiendrez l’erreur : Entity Id must be specified for Update.

Si vous n’avez pas de valeur de clé primaire, vous pouvez également mettre à jour les lignes à l’aide de clés secondaires. Informations complémentaires : Mettre à jour avec une clé secondaire

L’exemple suivant montre comment utiliser la classe Entity pour créer un compte à l’aide de la méthode IOrganizationService.Update.

var retrievedAccount = new Entity("account", new Guid("a976763a-ba1c-e811-a954-000d3af451d6"));

//Use Entity class with entity logical name
var account = new Entity("account");
account.Id = retrievedAccount.Id;
// set attribute values
// Boolean (Two option)
account["creditonhold"] = true;
// DateTime
account["lastonholdtime"] = DateTime.Now;
// Double
account["address1_latitude"] = 47.642311;
account["address1_longitude"] = -122.136841;
// Int
account["numberofemployees"] = 400;
// Money
account["revenue"] = new Money(new Decimal(2000000.00));
// Picklist (Option set)
account["accountcategorycode"] = new OptionSetValue(2); //Standard customer

//Update the account
svc.Update(account);

Utiliser la classe UpdateRequest

Au lieu d’utiliser la méthode IOrganizationService.Update, vous pouvez utiliser la classe Entity à liaison tardive ou les classes d’entité à liaison anticipée générées avec la classe UpdateRequest en définissant l’instance d’entité sur la propriété UpdateRequest.Target, puis en utilisant la méthode IOrganizationService.Execute.

Note

La classe UpdateResponse n’a aucune propriété. Lorsqu’elle est renvoyée par la méthode IOrganizationService.Execute, il n’est pas nécesssaire d’y faire référence.

var request = new UpdateRequest()
{ Target = account };
svc.Execute(request);

Quand utiliser la classe UpdateRequest

Vous devez utiliser la classe UpdateRequest si vous souhaitez transmettre des paramètres facultatifs. Il existe deux cas où vous pourriez avoir besoin de paramètres spéciaux.

Vous devez également utiliser la classe UpdateRequest si vous souhaitez préciser un comportement d’accès concurrentiel optimiste. Pour plus d’informations : Comportement de l’accès concurrentiel optimiste

Utilise la classe UpdateMultipleRequest

La classe UpdateMultipleRequest est le moyen le plus performant de mettre à jour plusieurs enregistrements dans une seule demande. Pour plus d’informations : Messages d’opération en bloc

De la même manière que vous pouvez Créer des lignes de table associées en une seule opération, vous pouvez également mettre à jour les lignes de tableau associées.

Pour mettre à jour les lignes de table associées, vous devez récupérer une ligne avec les lignes associées afin de pouvoir accéder aux valeurs d’ID. Pour plus d’informations : Extraire avec des lignes associées.

Important

Les mises à jour des lignes sont effectuées dans un ordre spécifique. Tout d’abord, les lignes du tableau principal sont traitées, puis les lignes du tableau associées sont traitées. Si une modification est apportée par la ligne principale pour une recherche ou une colonne de ligne associée, puis qu’une ligne associée met à jour la même colonne, la valeur de la ligne associée est conservée. En général, une valeur de colonne de recherche et son équivalent dans Entity.RelatedEntities pour la même relation ne doivent pas être utilisés en même temps.

var account = new Entity("account");
account.Id = retrievedAccount.Id;

//Define relationships
var primaryContactRelationship = new Relationship("account_primary_contact");
var AccountTasksRelationship = new Relationship("Account_Tasks");

//Update the account name
account["name"] = "New Account name";

//Update the email address for the primary contact of the account
var contact = new Entity("contact");
contact.Id = retrievedAccount.RelatedEntities[primaryContactRelationship]
.Entities.FirstOrDefault().Id;
contact["emailaddress1"] = "someone_a@example.com";

List<Entity> primaryContacts = new List<Entity>();
primaryContacts.Add(contact);  
account.RelatedEntities.Add(primaryContactRelationship, new EntityCollection(primaryContacts));

// Find related Tasks that need to be updated
List<Entity> tasksToUpdate = retrievedAccount
.RelatedEntities[AccountTasksRelationship].Entities
.Where(t => t["subject"].Equals("Example Task")).ToList();

// A list to put the updated tasks
List<Entity> updatedTasks = new List<Entity>();

//Fill the list of updated tasks based on the tasks that need to but updated
tasksToUpdate.ForEach(t => {
var updatedTask = new Entity("task");
updatedTask.Id = t.Id;
updatedTask["subject"] = "Updated Subject";

updatedTasks.Add(updatedTask);
});

//Set the updated tasks to the collection
account.RelatedEntities.Add(AccountTasksRelationship, new EntityCollection(updatedTasks));

//Update the account and related contact and tasks
svc.Update(account);

Rechercher des enregistrements dupliqués

Lors de la mise à jour d’une ligne de table, vous pouvez modifier les valeurs afin que la ligne représente un doublon d’une autre ligne. Pour plus d’informations : Détecter les données dupliquées avec le SDK pour .NET

Mettre à jour avec une clé secondaire

Si vous avez défini une clé secondaire pour une table, vous pouvez l’utiliser à la place de la clé primaire pour mettre à jour une ligne. Vous ne pouvez pas utiliser la classe à liaison anticipée pour spécifier la clé secondaire. Vous devez utiliser le constructeur Entity(String, KeyAttributeCollection) pour spécifier la clé secondaire.

Si vous souhaitez utiliser des types à liaison anticipée, vous pouvez convertir Entity en une classe à liaison anticipée à l’aide de la méthode Entity.ToEntity<T>.

L’exemple suivant montre comment mettre à jour un Account en utilisant un clé secondaire défini pour la colonne accountnumber (attribut).

Important

La plupart des tables de données d’entreprise n’ont pas de clés secondaires définies. Cette méthode ne peut être utilisée que lorsque l’environnement est configuré pour définir un clé secondaire pour une table.

var accountNumberKey = new KeyAttributeCollection();
accountNumberKey.Add(new KeyValuePair<string, object>("accountnumber", "123456"));

Account exampleAccount = new Entity("account", accountNumberKey).ToEntity<Account>();
exampleAccount.Name = "New Account Name";
svc.Update(exampleAccount);

Pour plus d′informations :

Mettre à jour et supprimer des enregistrements dans des tables élastiques

Si vous mettez à jour ou supprimez des données de table élastique stockées dans des partitions, assurez-vous de spécifier la clé de partition lors de l’accès à ces données. En savoir plus : Partitionnement et mise à l’échelle horizontale

Utiliser Upsert

Généralement dans les scénarios d’intégration des données, vous devez créer ou mettre à jour les données dans Dataverse depuis d’autres sources. Dataverse peut avoir déjà des enregistrements avec le même identifiant unique, qui peut être une clé secondaire. S’il existe une ligne de tableau, vous souhaitez la mettre à jour. S’il n’existe pas, vous souhaitez le créer de telle sorte que les données ajoutées sont synchronisées avec les données sources. Il s’agit du scénario lorsque vous souhaitez utiliser Upsert.

L’exemple suivant utilise deux fois UpsertRequest. La première fois que la ligne de compte est créée et la deuxième fois qu’elle est mise à jour car elle a une valeur accountnumber et une clé secondaire utilise cette colonne (attribut).

Pour les deux appels, la propriété UpsertResponse.RecordCreated indique si l’opération a créé une ligne ou non.

// This environment has an alternate key set for the accountnumber attribute.

//Instantiate account entity with accountnumber value
var account = new Entity("account", "accountnumber", "0003");
account["name"] = "New Account";

//Use Upsert the first time
UpsertRequest request1 = new UpsertRequest() {
Target = account
};

//The new entity is created
var response1 = (UpsertResponse)svc.Execute(request1);
Console.WriteLine("Record Created: {0}",response1.RecordCreated); //true

//Update the name of the existing account entity
account["name"] = "Updated Account";

//Use Upsert for the second time
UpsertRequest request2 = new UpsertRequest()
{
Target = account
};

//The existing entity is updated.
var response2 = (UpsertResponse)svc.Execute(request2);
Console.WriteLine("Record Created: {0}", response2.RecordCreated); //false

Pour plus d’informations : Utilisation de Upsert pour insérer ou mettre à jour un enregistrement

Delete

La méthode IOrganizationService.Delete requiert simplement le nom logique de la table et l’identificateur unique. Peu importe si vous utilisez une classe Entity à liaison tardive ou une classe à liaison anticipée générée, vous pouvez utiliser la syntaxe suivante pour une opération de suppression en transmettant les propriétés Entity.LogicalName et Entity.Id.

svc.Delete(retrievedEntity.LogicalName, retrievedEntity.Id);

Ou vous pouvez utiliser les valeurs :

svc.Delete("account", new Guid("e5fa5509-2582-e811-a95e-000d3af40ae7"));

Important

Les opérations de suppression peuvent lancer des opérations en cascade qui peuvent supprimer des lignes enfants pour maintenir l’intégrité des données en fonction de la logique définie pour le Relations dans l’environnement. Pour plus d’informations : Comportement des relations de table

Utiliser la classe DeleteRequest

Vous pouvez utiliser la classe DeleteRequest au lieu de la méthode IOrganizationService.Delete, mais elle n’est requise que lorsque vous souhaitez spécifier un comportement d’accès concurrentiel optimiste.

var retrievedEntity = new Entity("account")
{
    Id = new Guid("c81ffd82-cd82-e811-a95c-000d3af49bf8"),
    RowVersion = "986335"

};

var request = new DeleteRequest()
{
    Target = retrievedEntity.ToEntityReference(),
    ConcurrencyBehavior = ConcurrencyBehavior.IfRowVersionMatches
};

svc.Execute(request);

Comportement d’accès concurrentiel optimiste

Vous pouvez préciser le comportement d’accès concurrentiel optimiste pour l’opération en définissant la propriété ConcurrencyBehavior des classes UpdateRequest ou DeleteRequest.

La logique de mise à jour ou de suppression de la ligne peut être basée sur des données obsolètes. Si les données actuelles diffèrent, car elles ont changé depuis leur extraction, l’accès concurrentiel optimiste permet d’annuler une mise à jour ou de supprimer une opération de telle sorte que vous pouvez la récupérer et utiliser les données actuelles afin de déterminer s’il convient de poursuivre ou non.

Pour déterminer si la ligne a été modifiée, vous n’avez pas besoin de comparer toutes les valeurs, vous pouvez utiliser la propriété RowVersion pour voir si elle a changé.

L’exemple suivant se produit uniquement quand :

Si RowVersion ne correspond pas, une erreur survient avec le message The version of the existing record doesn't match the RowVersion property provided..

var retrievedAccount = new Account()
{   
    Id = new Guid("a976763a-ba1c-e811-a954-000d3af451d6"), 
    RowVersion = "986323" 
};

var account = new Account();
account.Id = retrievedAccount.Id;
account.RowVersion = retrievedAccount.RowVersion;

// set attribute values
account.CreditOnHold = true;

//Update the account
var request = new UpdateRequest()
{ 
    Target = account,
    ConcurrencyBehavior = ConcurrencyBehavior.IfRowVersionMatches 
};

try
{
    svc.Execute(request);
}
catch (FaultException<OrganizationServiceFault> ex)
{
    switch (ex.Detail.ErrorCode)
    {
        case -2147088254: // ConcurrencyVersionMismatch 
        case -2147088253: // OptimisticConcurrencyNotEnabled 
            throw new InvalidOperationException(ex.Detail.Message);
        case -2147088243: // ConcurrencyVersionNotProvided
            throw new ArgumentNullException(ex.Detail.Message);
        default:
            throw ex;
    }
}

Pour plus d’informations :

Anciens messages de mise à jour

Il existe plusieurs messages spécialisés déconseillés qui exécutent des opérations de mise à jour. Dans les versions antérieures, il était nécessaire d’utiliser ces messages, mais maintenant les mêmes opérations doivent être exécutées en utilisant IOrganizationService.Update ou la classe UpdateRequest avec la méthode IOrganizationService.Execute.

Demande de message déconseillé Attribut(s) à mettre à jour
AssignRequest <entity>.OwnerId
SetStateRequest <entity>.StateCode
<entity>.StatusCode
SetParentSystemUserRequest SystemUser.ParentSystemUserId
SetParentTeamRequest Team.BusinessUnitId
SetParentBusinessUnitRequest BusinessUnit.ParentBusinessUnitId
SetBusinessEquipmentRequest Equipment.BusinessUnitId
SetBusinessSystemUserRequest SystemUser.BusinessUnitId

<entity> fait référence à toute entité qui fournit cet attribut.

Important

Lorsque vous mettez à jour la colonne StateCode, il est important de toujours définir le StatusCode souhaité.

StateCode et StatusCode ont des valeurs dépendantes. Il peut y avoir plusieurs valeurs StatusCode valides pour une valeur StateCode donnée, mais chaque colonne StateCode a une seule valeur de DefaultStatus configurée. Lorsque vous mettez à jour StateCode sans spécifier de StatusCode, la valeur d’état par défaut est définie par le système.

De plus, lorsque l’audit est activé sur la table et la colonne StatusCode, la valeur modifiée de la colonne StatusCode ne sera pas capturée dans les données d’audit, sauf si elle est spécifiée dans l’opération de mise à jour.

Pour plus d’informations : Comportement des opérations de mise à jour spécifiques

Voir aussi

Créer des lignes de table à l’aide du SDK pour .NET
Récupérer une ligne de table à l’aide du SDK pour .NET
Associer et dissocier des lignes de tables à l’aide du SDK pour .NET