solidservices
solidservices copied to clipboard
Commands depending on other commands when using the decorator pattern for transaction
Hi,
I've been using your TransactionCommandHandlerDecorator and I came across a small problem when using this in conjunction with a command that has a dependency on another command as it is creating a second transaction block for the other command when I want it to share the same transaction?
Here is some code to demonstrate the problem.
Public Class TransactionCommandHandlerDecorator(Of TCommand)
Implements ICommandHandler(Of TCommand)
Private ReadOnly _decorated As ICommandHandler(Of TCommand)
Private ReadOnly _context As ApplicationDBContext
Public Sub New(context As ApplicationDBContext, decorated As ICommandHandler(Of TCommand))
_context = context
_decorated = decorated
End Sub
Public Sub Handle(command As TCommand) Implements ICommandHandler(Of TCommand).Handle
Using transaction = _context.Database.BeginTransaction()
Try
_decorated.Handle(command)
transaction.Commit()
Catch ex As Exception
transaction.Rollback()
Throw
End Try
End Using
End Sub
End Class
Public Class CreateProcedureTemplateDetailQuestionTypeHandler
Implements ICommandHandler(Of CreateProcedureTemplateDetailQuestionTypeCommand)
Private ReadOnly _context As ApplicationDBContext
Private ReadOnly _handler As ICommandHandler(Of CreateProcedureTemplateDetailCommand)
Public Sub New(context As ApplicationDBContext, handler As ICommandHandler(Of CreateProcedureTemplateDetailCommand))
_context = context
_handler = handler
End Sub
Public Sub Handle(command As CreateProcedureTemplateDetailQuestionTypeCommand)
Implements ICommandHandler(Of CreateProcedureTemplateDetailQuestionTypeCommand).Handle
_handler.Handle(command.DetailCommand)
'Do other stuff specific to this command
End Sub
End Class
But once I call handle inside of CreateProcedureTemplateDetailQuestionTypeHandler.Handle() I get an exception as it tries to create another transaction scope. What is the best way of dealing with this, should I just new up instance inside of the CreateProcedureTemplateDetailQuestionTypeHandler and not use DI for that case?
ith a command that has a dependency on another command
This is the core of your problem. My advise is to treat commands as holistic abstractions. This means that command handlers should not depend on other command handlers, especially not within the context of the same abstraction. You should use a different abstraction when dealing with 'sub commands'. This could be as well a generic abstraction, or you use normal non-generic interfaces for them.
What I have done is created a ICommandStrategyHandler and this is to be used by my sub command and the ICommandHandler is still decorated by the transaction. My instance of ICommandHandler then has a dependency on the new interface for it's sub command. This seems to have sorted it, but was checking to see if this is what you meant? This means that every instance of ICommandHandler will use the transaction but the other interface won't.
Seems legit.