5

Nous avons une application ASP.Net MVC qui utilise EF4 comme couche d'accès aux données et nous constatons un comportement inattendu en ce qui concerne OptimisitcConcurrencyExceptions n'étant pas lancé quand nous pensons qu'ils devraient être.Entity Framework Optimistic Concurrency Exception Exception non

Nous avons simplifié le problème à le code suivant ...

using System.Linq; 
    using Project.Model; 

    namespace OptimisticConcurrency 
    { 
     class Program 
     { 
      static void Main() 
      { 
       Contact firstContact = null; 
       using (var firstEntities = new ProjectEntities()) 
       { 
        firstContact = (from c in firstEntities.Contacts 
         where c.LastName == "smith" select c).Single(); 
       } 

       using (var secondEntities = new ProjectEntities()) 
       { 
        var secondContact = (from c in secondEntities.Contacts 
         where c.LastName == "smith" select c).Single(); 

        secondContact.Title = "a"; 
        secondEntities.SaveChanges(); 
       } 

       firstContact.Title = "b"; 

       using (var thirdEntities = new ProjectEntities()) 
       { 
        var thirdContact = (from c in thirdEntities.Contacts 
         where c.LastName == "smith" select c).Single(); 

        thirdContact.Title = firstContact.Title; 

        //EXPLICITLY SET VERSION HERE 
        thirdContact.Version = firstContact.Version; 

        thirdEntities.SaveChanges(); 
       } 
      } 
     } 
    } 

Ceci est une version assez simple de ce qui se passe dans notre application MVC, mais le même problème se produit. Lorsque nous appelons SaveChanges sur thirdEntities, j'attends l'exception et rien n'est levé. Bien plus intéressant, lorsque nous attachons le profileur SQL, nous voyons que la version est utilisée dans la clause where mais c'est la valeur de thirdEntities Version (celle en cours dans la BD) qui est utilisée, pas les valeurs firstEntities. étant explicitement défini immédiatement avant l'appel de SaveChanges. SaveChanges réinitialise la version pour qu'elle soit la valeur récupérée et non la valeur définie.

Dans EDMX, la version est configurée pour que StoreGeneratedPattern soit défini sur Computed.

Quelqu'un a-t-il une idée de ce qui se passe ici?

Répondre

9

Ceci est un problème. Une fois que la colonne est définie sur Computed, vous ne pouvez pas définir sa valeur dans l'application (vous pouvez mais la valeur n'est pas utilisée).

Edit:

Si vous chargez l'entité de base de données est par défaut suivi avec le contexte. Le contexte stocke ses valeurs d'origine. Les valeurs d'origine sont par exemple utilisées pour le suivi des modifications de clichés, mais elles sont également utilisées comme seule source valide de propriétés Computed. Si vous définissez la propriété Computed dans votre entité, la valeur n'est pas utilisée et la valeur d'origine est utilisée. La solution consiste à modifier la valeur d'origine (avant de modifier quoi que ce soit d'autre):

using (var context = new TestEntities()) 
{ 
    var entityToUpdate = context.MyEntities.Single(e => e.Id == someId); 
    entityToUpdate.Timestamp = entity.Timestamp; 

    ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(entityToUpdate); 
    entry.ApplyOriginalValues(entityToUpdate); 

    // set modified properties 
    context.SaveChanges(); 
} 

Edit 2:

btw. Une fois que vous avez à la fois l'horodatage réellement chargé et l'horodatage précédemment récupéré, vous pouvez simplement compare them in your application au lieu de le faire dans la base de données.

+1

Lorsque je définis la colonne Version sur StoreGeneratedPattern = None, une exception m'indique que je ne peux pas mettre à jour une colonne d'horodatage dans la base de données. –

+0

Oui, ce comportement ne fonctionne pas complètement. Je vais essayer une solution de contournement à la soirée et vous le faire savoir. –

Questions connexes