This project is read-only.

Database context in decorators

Aug 12, 2014 at 2:09 PM
Hi,

I am creating a fairly simple app which needs to use entity framework. I'm using simple injector and the command handler pattern.

So, I have DataContext that implements an EF DbContext and takes a connection string name in the constructor.

I have the following command handlers.
public class CreateProjectCommandHandler : ICommandHandler<CreateProjectCommand>
    {
        public CreateProjectCommandHandler()
        {
        }

        public CreateProjectCommand Handle(CreateProjectCommand command)
        {
            return command;
        }
    }
public class EntityFrameworkCommandHandler<TCommand> : ICommandHandler<TCommand>
    {
        private readonly DbContext context;
        private readonly ICommandHandler<TCommand> decorated;

        public EntityFrameworkCommandHandler(ICommandHandler<TCommand> decorated)
        {
            this.context = new DataContext("CONNECTION");
            this.decorated = decorated;
        }

        public TCommand Handle(TCommand command)
        {
            this.decorated.Handle(command);

            context.SaveChanges();

            return command;
        }
    }
I have simple injector configured like this.
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
                typeof(ICommandHandler<>).Assembly);

            container.RegisterDecorator(typeof(ICommandHandler<>),
                typeof(Services.Infrastructure.EntityFrameworkCommandHandler<>));
In EntityFrameworkCommandHandler id like to pass in the DbContext rather than creating it in the constructor. Is this possible?

I'd also like to be able use the same database context in the "decorated" handler. Is this just a matter of adding a new Handle method that takes the command and the dbcontext or is there a better way?

Any help on these would be appreciated.

Thanks
David
Aug 12, 2014 at 2:25 PM
I'd also like to be able use the same database context in the "decorated" handler. Is this just a matter of adding a new Handle method that takes the command and the dbcontext or is there a better way?
There definitely is a better way. You should not pass the DbContext on from method from method, because this will complicate your code. Instead, register the DbContext with a scoped lifestyle such as the WebRequestLifestyle:
container.RegisterPerWebRequest<DataContext>(() => new DataContext("CONNECTION"));
This will ensure that both the handler and the decorator get the same instance and allows the whole operation to be committed by the decorator.

I would also advice to let your ICommandHandler<TCommand> abstraction implement a void Handle method instead of returning the command itself. Returning the command is usually useless, since the client already has a reference to the command and it just forces all your handlers and decorators have an extra return statement.