How to check whether DbContext has transaction?

I think you're looking for the CurrentTransaction property of the DbContext:

var transaction = db.Database.CurrentTransaction;

Then you can do a check like this:

using(var transaction = db.Database.CurrentTransaction ?? db.Database.BeginTransaction())
{
   ...
}

However I'm not sure how you can know when to commit the transaction if it's being used by concurrent methods.


Instead of using the transaction from the DbContext of Entity Framework you could or maybe should use the TransactionScope class which creates an ambient transaction scope and manages transactions of all connections made to the (SQL) database under the covers.

It even would put a direct SqlCommand in the same transaction if you would use the exact (case-sensitive) connectionstring for the SqlCommand. Messages writen to the MessageQueue are also encapsulated in the same transaction

It even could manage connections to different databases at the same time. It uses the DTC windows service for this. Beware that this is a pain to configure if needed. Normally, with a single DB connection (or multiple connections to the same DB) you won't need the DTC.

The TransactionScopeCommandHandlerDecorator implementation is trivial:

public class TransactionScopeCommandHandlerDecorator<TCommand> 
        : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> decoratee;

    public TransactionScopeCommandHandlerDecorator(ICommandHandler<TCommand> decoratee)
    {
        this.decoratee = decoratee;
    }

    public void Handle(TCommand command)
    {
        using (var scope = new TransactionScope())
        {
            this.decoratee.Handle(command);

            scope.Complete();
        }
    }
}

But: As qujck already mentioned in the comments, you are missing the concept of ICommandHandler as an atomic operation. One commandhandler should never reference another commandhandler. Not only is this bad for transactions, but also consider this:

Imagine the application grows and you would refactor some of your commandhandlers to a background thread, which will run in some windows service. In this windows service a PerWcfOperation lifestyle is not available. You would need a LifeTimeScope lifestyle for you commandhandlers now. Because your design allows it, which is great by the way!, you would typicaly wrap your commandhandlers in a LifetimeScopeCommandHandler decorator to start the LifetimeScope. In your current design where a single commandhandler references other commandhandlers you will run into a problem, because every commandhandler will be created in its own scope a thus gets an other DbContext injected than the other commandhandlers!

So you need to do some redesign and make your commandhandlers holistic abstractions and create a lower level abstraction for doing the DbContext operations.