Una delle novità introdotte in Entity Framework 7.0 è la possibilità di effettuare update bulk e delete bulk. Queste due funzionalità sono molto utili perchè consentono di effettuare aggiornamenti e cancellazioni con performance notevolmente migliorate.
Partiamo però dall’inizio, cioè da come si potevano effettuare aggiornamenti bulk con entity framework 6.0.
La soluzione piu’ semplice è quella di estrarre i dati dal db e successivamente procedere con un loop aggiornando le proprietà con i nuovi valori, ed effettuare un salvataggio al termine di tutte le operazioni.
Ecco un esempio di questo tipo di aggiornamento:
var blogs = context.Blogs.ToList();
foreach(var element in blogs)
{
element.LastUpdated = Datetime.UtcNow
}
context.SaveChanges();
Facciamo ora qualche considerazione relativamente alla gestione degli aggiornamenti: supponiamo di non aver modifcato la dimensione dei batch di aggiornamento (impostata per default a 42), e supponendo di dover aggiornare 500 records nel blog, verrebbero generati 12 roundtrip di aggiornamento (500 records/ 42 batch size).
Questo tipo di aggiornamento è sicuramente inefficiente, perchè il numero di round trip è sicuramente elevato e soprattutto perchè contiene al suo interno un alto numero di update. Queste update vengono inviate a blocchi separati, e vengono eseguite sul database in maniere indipedente e separata l’una dall’altra.
Non stiamo sicuramente ottimizzando le performance per l’operazione di update.
Una soluzione possibile potrebbe essere quellai bypassare l’utilizzo del model di entity framework e di utilizzare ADO.NET: questa soluzione prevede la creazione di N istruzioni di update e l’esecuzione raw sul database.
connection.Open();
using(var sqlCommand = new SqlCommand("UPDATE BLOGS SET LastUpdate=@date; --ADONETUPDATE", connection))
{
command.Parameters.AddWithValue("@date",DateTime.UtcNow);
command.ExecuteNonQuery();
}oppure in alternativa usare context.Database.ExecuteSql(…..) in modo da eseguire la query direttamente sul db.
Questo tipo di approccio produce una singola dichiarazione per l’update, che aggiornerà i dati con un roundtrip per ogni singolo comando.
Utilizzando query semplici rispetto all’utilizzo di Entity Framework 6 può comportare migliorie e differenze nelle performance sicuramente migliori.
Ed ecco quindi che ci troviamo davanti ad una delle novità piu importanti presenti in entity framework 7: la possibilità di usare il comando ExecuteUpdate che constente di effettuare l’aggiornamento in modalità batch.
La sintassi è piuttosto semplice e compatta:
using var context = new MyContext(); context.Blogs.ExecuteUpdate(s=>s.SetProperty(blog=>blog.LastUpdate, DateTime.UtcNow));
In questo caso stiamo effettuando l’update di una singola proprietà, ma è possibile aggiornarne piu di una creando una chaing direttamente sulla SetProperty.
Quello che viene generato a livello di entity framework è qualcosa del tipo:
UPDATE [b] SET [b].[LastUpdated] = GETUTCDATE() FROM [Blogs] as [B]
Anche in questo caso siamo in presenza di una singola istruzione di aggiornamento, ma fortemente tipizzata.
Sicuramente l’utilizzo di ADO.NET per molte applicazioni potrebbe risultare la soluzione migliore e piu veloce nell’esecuziozione. L’utilizzo di ExecuteUpdate() è sicuramente una valida alternativa, perchè consente di rimanere in un ambiente fortemente tipizzato e soprattutto refactor safe.