Prendendo sempre come riferimento il database e gli esempi creati nei precedenti episodi, vediamo due possibili strategie per la gestione della concorrenza (ottimistica) in EF CTP5: Store Wins e Client Wins.
Store Wins
using (Db db = new Db())
{
Developer developer = (from d in db.Developers select d).FirstOrDefault();
////Modifica del cognome
developer.Surname = "Cognome";
////In un altro punto dell’applicazione il cognome viene cambiato in “Libro”
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
////Ricarica i dati dal database.
ex.GetEntry(db).Reload();
////A meno di un merge o scelte dell’utente, sul database viene persistito “Libro”.
db.SaveChanges();
}
}
In questo caso recuperiamo la prima entità Developer presente nel database e modifichiamo il valore della proprietà Surname. Supponendo che qualcuno esegua la persistenza dei dati (ovvero cambi il valore del campo cognome della tabella di riferimento) prima del “nostro” SaveChanges(), quando cerchiamo di persistere le modifiche da noi apportate viene sollevata un’eccezione DbUpdateConcurrencyException. Nel caso di una strategia Store Wins recuperiamo i dati (aggiornati) nel database tramite Reload() ed eseguiamo il SaveChanges() che dovrebbe andare a buon fine, tranne se nel frattempo siano state apportate ulteriori modifiche ai dati su cui stiamo agendo. A tal proposito sarebbe opportuno eseguire un merge “automatico” dei dati o meglio visualizzare i cambianti all’utente che quindi potrà scegliere di cambiare\sovrascrivere i dati o annullare le operazioni.
Client Wins
using (Db db = new Db())
{
Developer developer = (from d in db.Developers select d).FirstOrDefault();
Assert.IsNotNull(developer);
////Modifica del cognome
Developer.Surname = "Cognome";
////In un altro punto dell’applicazione il cognome viene cambiato in “Libro”
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
DbEntityEntry developer = ex.GetEntry(db);
////Settiamo i valori “Original” delle proprietà con i valori presenti nella base di dati
////Questo non crea problemi di concorrenza (o almeno non dovrebbe) al prossimo SaveChanges.
developer.OriginalValues.SetValues(customer.GetDatabaseValues());
db.SaveChanges();
}
}
Nel secondo caso, in caso di eccezione dovuta alla gestione della concorrenza ottimistica, i valori “Currents” della proprietà dell’entità Developer che stiamo modificando sono settati con i valori correntemente persistiti nella base di dati, in questo modo, a meno di ulteriori modifiche sul database, quando richiamiamo SaveChanges() riusciamo a persistere le nostre modifiche. Anche in questo caso potrebbe essere scelta una politica di decisione che rende l’utente responsabile delle operazioni da effettuare.
Per indicare ad Entity Framework quali sono le proprietà che entrano in gioco durante la gestione della concorrenza, utilizziamo l’attributo:
[ConcurrencyCheck]
[...]
public virtual string Surname