Nested Transaction Behavior in EF6

c# entity-framework entity-framework-6 transactions

Question

I've been having trouble with nested transactions and async where the connection seems to close during the nested transaction or the transaction is promoted to MSDTC. I'm currently using TransactionScope to manage transactions in my data layer. Although I haven't yet identified the precise issue, it appears from reading that this scenario isn't supported by especially well and that I should instead be utilizing a database. Instead, use BeginTransaction().

The issue I'm having is that I can't seem to find any information on how Database.BeginTransaction() handles nested transactions, which is problematic given that in my case I want to use the ambient transaction rather than start a new one. I have a sneaking hunch that this isn't how it's supposed to operate, and that if I want to manage stacked transactions, I should abstract off transaction management altogether.

I was wondering if someone had experience in this area and could validate the behavior of the Database because I didn't want to add any extra layers of abstraction. When nested inside another transaction, can I use BeginTransaction()?

I tend to encapsulate Db-related code in command or query handlers based on the CQS pattern, therefore an abridged/artificial example of how this layering occurs would be:

public class AddBlogPostHandler
{
    private readonly MyDbContext _myDbContext;

    public AddBlogPostHandler(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

    public async Task ExecuteAsync(AddBlogPostCommand command)
    {
        using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            // .. code to create and add a draft blog post to the context
            await _myDbContext.SaveChangesAsync();

            var publishBlogPostCommand = new PublishBlogPostCommand();
            // ..set some variables on the PublishBlogPostCommand
            await PublishBlogPostAsync(command);

            scope.Complete();
        }
    }
}

public class PublishBlogPostHandler
{
    private readonly MyDbContext _myDbContext;

    public PublishBlogPostHandler(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

    public async Task ExecuteAsync(PublishBlogPostCommand command)
    {
        using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            // .. some code to do one set of update
            await _myDbContext.SaveChangesAsync();

            // .. some other db updates that need to be run separately
            await _myDbContext.SaveChangesAsync();

            scope.Complete();
        }
    }
}
1
12
12/8/2015 3:29:56 PM

Accepted Answer

ZZZ_tmp
7
12/8/2015 3:37:31 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow