Entity Framework, commit/rollback e transazioni
Vi capita di vedere questo messaggio da Entity Framework?
New transaction is not allowed because there are other threads running in the session.
Succede quasi sempre all’interno di cicli (for, while e simili) in cui viene chiamato SaveChanges(). Probabilmente dovete spezzare la logica dei vostri loop di aggiornamento dati: spesso è sufficiente portare SaveChanges() fuori dal ciclo. Oppure potete usare le transazioni.
Merita un appunto questo pezzo di codice, che serve a gestire anche transazioni annidate. Prima un metodo che crea una TransactionScope con livello di isolamento e timeout espliciti:
public TransactionScope CreateTransactionScope()
{
var transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
transactionOptions.Timeout = TimeSpan.MaxValue;
return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
}
Poi il salvataggio di due contesti dentro un’unica transazione:
using (TransactionScope scope = CreateTransactionScope())
{
// Salva le modifiche mantenendo lo stato corrente di context1.
context1.SaveChanges(SaveOptions.DetectChangesBeforeSave);
// Salva le modifiche mantenendo lo stato corrente di context2.
context2.SaveChanges(SaveOptions.DetectChangesBeforeSave);
// Se siamo arrivati qui il commit è riuscito: completa la transazione.
scope.Complete();
// Ora è sicuro aggiornare lo stato dei contesti.
context1.AcceptAllChanges();
context2.AcceptAllChanges();
}
Se viene sollevata un’eccezione prima di scope.Complete(), la transazione viene annullata e i contesti mantengono le modifiche in sospeso.
Articolo originale: luisrocha.net. Happy coding!