in C#, Informatica

Entity Framework 7 bulk update

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.