Search code examples
.netmongodbcqrs

CQRS, Event Sourcing and NoSQL database


We're starting a new project where we want to implement CQRS + Event Sourcing architecture with MongoDB. We already have some experience with CQRS approach: in our previous project we took Fohjin framework as a starting point (well, we refactored it significantly). We used Oracle as a storage and also implemented a 2PC with TransactionScope in that case.

But for our new project we want to use MongoDB due to its scalability and performance. We definitely want to use it for read (report) part and cosidering it for an event store. The alternative here is to use SQL Server for event storage. So we need to make a choice. What I don't like about hybrid solution is TransactionScope which is expensive and slow and necessity to support different Db types (Mongo and SQL).

We looked at NCQRS, but it seems that we do not want to depend highly on any framework, which dictates a lot of things that can be implemented differenly from our point of view. So now we're thinking of something more lightweight like Jonathan Oliver's Event Store. I like the concept of streams and commits and it also supports MongoDB. What I still do not understand, how it handles all that 2PC stuff (it is stated, that for NoSQL). In our case we need to dipatch events to several event handlers: some kind of denomalizer which updates the read database and task sheduler for a certain types of events. If something goes wrong with these handlers and we got an exeption, there is no way to roll back a commit for MongoDB. Is there any trick to handle this?

I appreciate any comments on how to make the right decision and what are pros and cons.


Solution

  • The EventStore uses a Guid to uniquely identify a commit against the database to prevent the same stream of events from being persisted more than once. Typically this Guid is embedded directly in a message, uniquely identifying that particular message, and can be used as the CommitId when calling CommitChanges on the event stream. You could use a similar approach when handling events on the query side of your system.

    Some more info on 2PC and avoiding distributed transactions: