Instead of using a transaction from a DbContext from the Entity Framework, you can, or perhaps should, use the TransactionScope class, which creates an external transaction and manages the transactions of all database connections (SQL) under covers.
It would even put the direct SqlCommand in the same transaction if you use the exact (case-sensitive) connection string for SqlCommand . Messages recorded in MessageQueue are also enclosed in a single transaction.
He could simultaneously manage the connection to various databases. He uses the DTC service for this. Beware that this is a pain when setting up if necessary. Usually with a single DB connection (or multiple connections to the same DB), you do not need a DTC.
The implementation of TransactionScopeCommandHandlerDecorator 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 mentioned in the qujck comments, you are losing the concept of ICommandHandler as an atomic operation. One command manipulator should never reference another manipulator. This is not only bad for transactions, but also takes this into account:
Imagine that the application is growing, and you will refactor some of your command handlers into a background thread that will work on some Windows services. PerWcfOperation not available PerWcfOperation this Windows service. Now you will need a LifeTimeScope lifestyle for you. Because your design allows this, which is great, by the way !, you would typically wrap your commanders in a LifetimeScopeCommandHandler decorator to run LifeTimeScope . In your current project, where one command manipulator refers to other command manipulators, you will run into a problem because each manipulator will be created in its own area. Thus, it gets a different DbContext than other manipulators!
So, you need to do some redesigns and make your cmdlets complete abstractions and create a lower level abstraction to perform DbContext operations.
source share