0

I was looking for an easy implementation of the Event Sourcing and CQRS Pattern in ASP.NET Core using Azure Cosmos DB as Event Store.

As I couldn't find anything appropriate I decided to write a solution using the mentioned technology stack on my own.

The ASP.NET Core Backend receives commands, creates events and writes it in the event store. The Azure Function processes incoming events and calculates a materialized view containing an account with the current balance and status based on the events received.

I put the source code on GitHub: https://github.com/marxxxx/EventSourcingCqrsDemo

I would say, it's basically working but there is one thing I did not understand enough to get it right.

One of the domain rules is: You can only transfer as much money as it is available on your account. I put this check in the domain object (Account). However, as the Domain Object is just used in the Azure Function to calculate the latest version of the Materialized View, an error would just be raised when processing the event. The user of the Web Api, issuing the faulty transfer is not informed directly as part of the HTTP response.

So my questions would be: - Is it common when using this kind of patterns to duplicate the domain rule check if I need instant execution of domain rules as part of the request? - Is my understanding of commands vs events wrong? Did I use the domain object in the wrong place? Should I use it when handling the incoming request/command to generate the domain events?

Thank you very much for any feedback.

  • 1
    How is it that a TransferMoney event is raised when an Account doesn't have enough money? Events should be raised in response to changes of state. – king-side-slide Apr 10 at 15:10
  • Thank you for your response! Well, in my WebApi i receive commands. When i receive the "TransferMoney" command, currently i build the current version of my Source Account Domain Object and the current version of my Destination Account Domain Object. Then i build the event "BalanceDecreased" and pass it the DecreaseBalance-Method of the Source Account (which performs the check if enough balance is available and decreases the balance). – Markus S. Apr 10 at 15:45
  • Then i do the opposite for the other account to increase the balance. This feels wrong and this is also stated by your comment because actually to my understanding, the domain object should receive a command and react with events, right? – Markus S. Apr 10 at 15:45
  • 1
    You are correct that your domain objects will either need to be injected with the ability to raise events or present an interface through which the events they raise can be inspected. Regarding injection, there are two camps here: You can either inject the EventStore into all of your entities or simply make the EventStore static. While the second option may not seem as pure, it can help simplify a system. In practice I find a static store to often be the most pragmatic. The other option is to have each entity store it's events locally and provide an interface... – king-side-slide Apr 10 at 16:31
  • 1
    ... for your infrastructure to retrieve them. I personally don't like this option. Lastly, as you have astutely pointed out, the paradigm of consuming commands that change state and raise events in response could result in some duplication if implemented naively. Often the pattern here is to only check invariants and raise events in your command-handling methods. By having each entity subscribe to it's own events you can centralize mutations in the event-handling methods in a way that allows the same code paths during construction and mutation. – king-side-slide Apr 10 at 16:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.