Torna al Blog

    Entity Framework, commit/rollback and transactions

    12 settembre 2014

    Do you often get this message from Entity Framework?

    New transaction is not allowed because there are other threads running in the session.

    This usually happens when you have a SaveChanges() call inside a loop. Then probably you must break the logic of your data update loops, for example by taking SaveChanges() out of the loop. Or you can use transactions.

    The following snippet works also for nested transactions. First, a helper that creates a TransactionScope with an explicit isolation level and timeout:

    public TransactionScope CreateTransactionScope()
    {
        var transactionOptions = new TransactionOptions();
        transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
        transactionOptions.Timeout = TimeSpan.MaxValue;
    
        return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
    }

    Then, saving two contexts inside a single transaction:

    using (TransactionScope scope = CreateTransactionScope())
    {
        // Save changes but maintain context1 current state.
        context1.SaveChanges(SaveOptions.DetectChangesBeforeSave);
    
        // Save changes but maintain context2 current state.
        context2.SaveChanges(SaveOptions.DetectChangesBeforeSave);
    
        // Commit succeeded since we got here, then completes the transaction.
        scope.Complete();
    
        // Now it is safe to update context state.
        context1.AcceptAllChanges();
        context2.AcceptAllChanges();
    }

    If an exception is thrown before scope.Complete(), the transaction is rolled back and the contexts keep their pending changes.

    Original article: luisrocha.net. Happy coding!