Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should we persist this to the database? #16

Open
ghost opened this issue May 1, 2020 · 2 comments
Open

Should we persist this to the database? #16

ghost opened this issue May 1, 2020 · 2 comments

Comments

@ghost
Copy link

ghost commented May 1, 2020

Hey Kamil,
First thanks for the great example! I'm learning a lot from it!
While creating a new order I can't see where those are persisted on the database and consequently can't see any processing of outbox item.
Is it the case that we should persist the order on the db after the line bellow?

@kgrzybek
Copy link
Owner

kgrzybek commented May 1, 2020

Hi @lisandropacheco,

All command handlers are decorated by UnitOfWork decorator:
https://github.com/kgrzybek/sample-dotnet-core-cqrs-api/blob/master/src/SampleProject.Infrastructure/Processing/UnitOfWorkCommandHandlerWithResultDecorator.cs

    public class UnitOfWorkCommandHandlerWithResultDecorator<T, TResult> : ICommandHandler<T, TResult> where T : ICommand<TResult>
    {
        private readonly ICommandHandler<T, TResult> _decorated;
        private readonly IUnitOfWork _unitOfWork;

        public UnitOfWorkCommandHandlerWithResultDecorator(
            ICommandHandler<T, TResult> decorated, 
            IUnitOfWork unitOfWork)
        {
            _decorated = decorated;
            _unitOfWork = unitOfWork;
        }

        public async Task<TResult> Handle(T command, CancellationToken cancellationToken)
        {
            var result = await this._decorated.Handle(command, cancellationToken);

            await this._unitOfWork.CommitAsync(cancellationToken);

            return result;
        }
    }

After the command is handled by CommandHandler, this decorator invokes UnitOfWork.CommitAsync method which publishes all events and saves changes to the database:

    public class UnitOfWork : IUnitOfWork
    {
        private readonly OrdersContext _ordersContext;
        private readonly IDomainEventsDispatcher _domainEventsDispatcher;

        public UnitOfWork(
            OrdersContext ordersContext, 
            IDomainEventsDispatcher domainEventsDispatcher)
        {
            this._ordersContext = ordersContext;
            this._domainEventsDispatcher = domainEventsDispatcher;
        }

        public async Task<int> CommitAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            await this._domainEventsDispatcher.DispatchEventsAsync();
            return await this._ordersContext.SaveChangesAsync(cancellationToken);
        }
    }

This is the implementation of the Chain Of Responsibility pattern when one object is processed by several handlers. Each handler has own responsibility (logging, validating, saving, processing) and a pointer to the next handler.

@astrobolidos
Copy link

Hey Kamil, thanks for the quick answer. I'm the same lisandropacheco. The initial question was linked to an older git hub work account that now has been deleted. That's why I didn't get the notification to our answer before!
It must be something with running from a mac because even the unit testing PlaceOrder_Test is failing.
follows the stack trace:
at SampleProject.Application.Orders.GetCustomerOrderDetails.GetCustomerOrderDetailsQueryHandler.Handle(GetCustomerOrderDetailsQuery request, CancellationToken cancellationToken) in /Users/lisandropacheco/Documents/src/sample-dotnet-core-cqrs-api/src/SampleProject.Application/Orders/GetCustomerOrderDetails/GetCustomerOrderDetailsQueryHandler.cs:line 41
at MediatR.Pipeline.RequestPreProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at MediatR.Pipeline.RequestPostProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next)
at SampleProject.Infrastructure.Processing.QueriesExecutor.Execute[TResult](IQuery1 query) in /Users/lisandropacheco/Documents/src/sample-dotnet-core-cqrs-api/src/SampleProject.Infrastructure/Processing/QueriesExecutor.cs:line 16 at SampleProject.IntegrationTests.Orders.OrdersTests.PlaceOrder_Test() in /Users/lisandropacheco/Documents/src/sample-dotnet-core-cqrs-api/src/Tests/SampleProject.IntegrationTests/Orders/OrdersTests.cs:line 33 at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter1.BlockUntilCompleted()
at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaitable)
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.b__0()
at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants