Domanda

Abbiamo un'applicazione ASP.Net MVC che utilizza EF4 come il suo livello di accesso ai dati e stiamo vedendo un comportamento imprevisto per quanto riguarda OptimisitcConcurrencyExceptions non essere gettati quando pensiamo che dovrebbero essere.

Abbiamo semplificato il problema verso il seguente codice ...

   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();
                }
            }
        }
    }

Questa è una versione piuttosto semplice di ciò che accade nella nostra MVC app, ma lo stesso problema si verifica.

Quando chiamiamo SaveChanges sui thirdEntities, mi aspetto l'eccezione e nulla viene gettata.

Molto più interessante, quando si allega il Profiler SQL, vediamo che la versione viene utilizzato nella clausola WHERE ma è valore thirdEntities versione (quella attuale nel DB) in uso, non i valori firstEntities nonostante che sia esplicitamente impostare immediatamente prima SaveChanges si chiama. SaveChanges sta resettando la versione di essere il non valore recuperato il valore impostato.

Nel EDMX, la versione è impostato per avere uno StoreGeneratedPattern è impostato su computerizzata.

Qualcuno ha idea di cosa sta succedendo qui?

È stato utile?

Soluzione

Questo è un problema. Una volta che la colonna è impostata su Computed Non si può impostare il suo valore nell'applicazione (è possibile, ma il valore non è utilizzato).

Modifica

Se si carica un'entità dal database è di default rintracciato con il contesto. Il contesto memorizza i suoi valori originali. valori originali sono per esempio utilizzati per il cambiamento snapshot di monitoraggio, ma sono utilizzati anche come l'unica fonte valida di proprietà Computed. Se si imposta la proprietà Computed nel vostro soggetto il valore non viene utilizzato e il valore originale viene utilizzato insted. La soluzione è modificare il valore originale (prima di modificare qualsiasi altra cosa):

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();
}

Modifica 2:

Btw. una volta che avete sia effettivamente caricato timestamp e recuperati in precedenza timestamp si può semplicemente confrontarli nel vostro applicazione invece di farlo nel database.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top