Entity Framework 6 transaction rollback

c#, entity-framework, entity-framework-6, sql-server, transactions

Solution

You don't need to call `Rollback` manually because you are using the `using` statement.

`DbContextTransaction.Dispose` method will be called at the end of the `using` block. And it will automatically rollback the transaction if the transaction is not successfully committed (not called or encountered exceptions). Following is the source code of `SqlInternalTransaction.Dispose` method (`DbContextTransaction.Dispose` will finally delegate to it when using SqlServer provider):

private void Dispose(bool disposing)
{
    // ...
    if (disposing && this._innerConnection != null)
    {
        this._disposing = true;
        this.Rollback();
    }
}

You see, it checks if `_innerConnection` is not null, if not, rollback the transaction (if committed, `_innerConnection` will be null). Let's see what `Commit` does:

internal void Commit() 
{
    // Ignore many details here...
    
    this._innerConnection.ExecuteTransaction(...);

    if (!this.IsZombied && !this._innerConnection.IsYukonOrNewer)
    {
        // Zombie() method will set _innerConnection to null
        this.Zombie();
    }
    else
    {
        this.ZombieParent();
    }

    // Ignore many details here...
}

internal void Zombie()
{
    this.ZombieParent();

    SqlInternalConnection innerConnection = this._innerConnection;

    // Set the _innerConnection to null
    this._innerConnection = null;

    if (innerConnection != null)
    {
        innerConnection.DisconnectTransaction(this);
    }
}

Problem

With EF6 you have a new transaction which can be used like: ``` using (var context = new PostEntityContainer()) { using (var dbcxtransaction = context.Database.BeginTransaction()) { try { PostInformation NewPost = new PostInformation() { PostId = 101, Content = "This is my first Post related to Entity Model", Title = "Transaction in EF 6 beta" }; context.Post_Details.Add(NewPost); context.SaveChanges(); PostAdditionalInformation PostInformation = new PostAdditionalInformation() { PostId = (101), PostName = "Working With Transaction in Entity Model 6 Beta Version" }; context.PostAddtional_Details.Add(PostInformation); context.SaveChanges(); dbcxtransaction.Commit(); } catch { dbcxtransaction.Rollback(); } } } ``` Is rollback actually needed when things go sideways? I'm curious because the Commit description says: "Commits the underlying store transaction." Whereas the Rollback description says: "Rolls back the underlying store transaction." This makes me curious, because it looks to me that if Commit isn't called, the previously executed commands will not be stored (which seems logical to me). But if that is the case, what would the reason be to call the Rollback function? In EF5 I used TransactionScope which didn't have a Rollback function (only a Complete) which seemed logical to me. Due to MS DTC reasons I cannot use the TransactionScope anymore, but I also cannot use a try catch like the example above (i.e., I only need the Commit).

Original source

Related problems