Partager via


Enregistrement des modifications et gestion de l'accès concurrentiel (Entity Framework)

Entity Framework implémente un modèle d'accès concurrentiel optimiste. Cela signifie que les verrous ne sont pas maintenus sur les données de la source de données. Toutefois, par défaut, Object Services enregistre les modifications des objets dans la base de données sans vérifier l'accès concurrentiel. Pour les propriétés qui peuvent connaître un accès concurrentiel de haut niveau, nous recommandons que la propriété d'entité soit définie dans la couche conceptuelle avec un attribut ConcurrencyMode="fixed", comme l'illustre l'exemple suivant :

<Property Name="Status" Type="Byte" Nullable="false" ConcurrencyMode="Fixed" />

Lorsque cet attribut est utilisé, Object Services recherche des modifications dans la base de données avant d'enregistrer les modifications dans la base de données. Toutes les modifications en conflit provoqueront un OptimisticConcurrencyException. Pour plus d'informations, voir Procédure : gérer l'accès concurrentiel aux données dans le contexte de l'objet (Entity Framework). Une exception OptimisticConcurrencyException peut également se produire lorsque vous définissez un modèle EDM (Modèle de données d'entité) qui met à jour la source de données à l'aide de procédures stockées. Dans ce cas, l'exception est levée lorsque la procédure stockée utilisée pour effectuer des mises à jour signale qu'aucune ligne n'a été mise à jour. Pour plus d'informations, voir Prise en charge des procédures stockées (Entity Framework).

Lorsque vous effectuez des mises à jour dans de tels scénarios à fort accès concurrentiel, nous vous recommandons d'appeler fréquemment Refresh. Lorsque vous appelez Refresh, le RefreshMode contrôle la manière dont les modifications sont propagées. L'option StoreWins spécifiera à Object Services de remplacer toutes les données dans le cache d'objet par les valeurs correspondantes dans la base de données. Inversement, l'option ClientWins remplace les valeurs d'origine dans le cache par les valeurs les plus récentes de la source de données. Vous êtes ainsi assuré que toutes les données modifiées dans le cache d'objet peuvent être enregistrées avec succès en retour dans la source de données. Les conflits entre les modifications de données dans le cache et les modifications que vous avez apportées aux mêmes données dans la source de données sont éliminés.

Appelez la méthode Refresh après la méthode SaveChanges si les mises à jour apportées à la source de données sont susceptibles de modifier les données appartenant aux autres objets du contexte d'objet. Par exemple, dans le modèle de vente AdventureWorks Sales Model, lorsqu'un nouveau SalesOrderDetail est ajouté, des déclencheurs metttent à jour la colonne SubTotal pour indiquer le sous-total avec le nouvel élément. Dans ce cas, appelez la méthode Refresh et transmettez l'objet SalesOrderHeader pour la commande. Vous êtes ainsi assuré que les valeurs générées par déclencheur sont renvoyées à l'objet SalesOrderHeader dans le contexte de l'objet.

Object Services effectue le suivi des modifications qui ont été apportées aux objets dans le cache. Lorsque la méthode SaveChanges est appelée, Object Services tente de fusionner en retour les modifications dans la source de données. SaveChanges peut échouer avec une exception OptimisticConcurrencyException lorsque les modifications des données dans le cache d'objet sont en conflit avec les modifications apportées dans la source de données après que les objets ont été ajoutés ou actualisés dans le cache. Cela entraîne l'annulation de la transaction entière. Lorsqu'une exception OptimisticConcurrencyException se produit, vous devez la traiter en appelant Refresh et en précisant si le conflit doit être résolu en préservant les données dans les données d'objet (ClientWins) ou en mettant à jour le cache d'objet avec les données de la source de données (StoreWins), comme dans l'exemple suivant :

Try
    ' Try to save changes, which may cause a conflict.
    Dim num As Integer = context.SaveChanges()
    Console.WriteLine("No conflicts. " + _
                      num.ToString() + " updates saved.")
Catch ex As OptimisticConcurrencyException
    ' Resolve the concurrency conflict by refreshing the 
    ' object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders)

    ' Save changes.
    context.SaveChanges()
    Console.WriteLine("OptimisticConcurrencyException " _
                      + "handled and changes saved.")
End Try
try
{
    // Try to save changes, which may cause a conflict.
    int num = context.SaveChanges();
    Console.WriteLine("No conflicts. " +
        num.ToString() + " updates saved.");
}
catch (OptimisticConcurrencyException)
{
    // Resolve the concurrency conflict by refreshing the 
    // object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders);

    // Save changes.
    context.SaveChanges();
    Console.WriteLine("OptimisticConcurrencyException "
    + "handled and changes saved");
}

SaveChanges peut générer une exception UpdateException lorsqu'un objet ajouté à ObjectContext ne peut pas être créé dans la source de données. Cela peut se produire si une ligne associée à la clé étrangère spécifiée par la relation existe déjà. Dans ce cas, vous ne pouvez pas utiliser Refresh pour mettre à jour l'objet ajouté dans le contexte de l'objet. À la place, rechargez l'objet avec une valeur de OverwriteChanges pour MergeOption.

Pour plus d'informations sur la gestion du contexte de l'objet, voir Procédure : gérer l'accès concurrentiel aux données dans le contexte de l'objet (Entity Framework).

Object Services honore également les transactions qui ont été définies en utilisant l'espace de noms System.Transactions. Pour plus d'informations, voir Gestion des transactions dans Object Services (Entity Framework).

Voir aussi

Concepts

Ajout, modification et suppression d'objets (Entity Framework)

Autres ressources

Utilisation d'objets (Entity Framework)