Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CQRS - The query side

People also ask

What is the CQRS pattern?

Storage. CQRS stands for Command and Query Responsibility Segregation, a pattern that separates read and update operations for a data store. Implementing CQRS in your application can maximize its performance, scalability, and security.

What is a query handler in CQRS?

Command query responsibility segregation (CQRS) is a programming design pattern that treats retrieving data and changing data differently. CQRS uses command handlers to simplify the query process and hide complex, multi-system changes.

Is CQRS an architecture or pattern?

CQRS is a popular architecture pattern because it addresses a common problem to most enterprise applications. Separating write behavior from read behavior, which the essence of the CQRS architectural pattern, provides stability and scalability to enterprise applications while also improving overall performance.

What problem does CQRS solve?

CQRS allows you to define commands with enough granularity to minimize merge conflicts at the domain level (any conflicts that do arise can be merged by the command), even when updating what appears to be the same type of data.


Yeah, there's a confusion that arises. Here's how it happens: First, in order to really help new people understand what CQRS is all about, and to really drive home how it differs from the typical layered architecture, people say things like, "Your view models can be completely flat", and "You should have one table per view model in your Query database."

But that is really just meant to drive the point home ... it is not true that you must have only one table per view model (though in most cases you probably should). What those statements are trying to say is this: "You've got to shake yourself free of some rules that you've followed for so long about normalization. With the CQRS architecture, you have the opportunity to make database tables in your Query channel that are completely shaped according to the needs of your view and nothing else. Make sure you take full advantage of that. Don't go halfway by normalizing these tables just because it is what you're accustomed do. Instead, go ahead and do things that used to be considered unthinkable, such as making one database table per view model, or making your view model tables completely flat."

There are still cases such as yours where the schema that would best serve your needs would have multiple tables. You might even (God forbid) do a Join or two. That's fine, as long as you really have designed the database tables to serve your view, and not vice versa. But be careful, it is easy to slip down the slope of normalization and sharing data between many views in the Query database. Don't go there ... there's simply no reason and it incurs more cost than benefit. The main goal is this: Your View logic should be dead, dead simple. You want the intelligent rules living on the Command side of the house, and a little bit in the Subscribers that populate the data in the Query channel. So the code that reads from the Query database and shows data on a screen should be dead simple (almost as simple as a "passive view").

Update: As further backing for the statement that it is not "forbidden" to do some joins as long as you have designed the database shape to best serve the task you're achieving, consider OLAP. The star schema is a perfect example of a database schema designed to support reads, that fits perfectly in the Query side of CQRS, and that does involve joins. The joins are kept simple, and they are in place to further enhance the goals of the Read tasks performed against the database.


if anyone is actually saying that your viewmodels should be flat, they are either oversimplifying their example or they are talking a bunch of nonsense. hierarchical data is not bad and should not be avoided in your viewmodels.

there really are no 'best practices' for this, though. it's all very subjective in how you load up the data. you need to find a solution that works well for your current team and system. and you should also understand what other options are out there because you'll probably run into a situation where your current solution is inadequate.

here are some of the ways I handle this, depending on the application i'm working on, in C# / .NET:

  • Datasets and straight ADO.NET, and bind the dataset directly to the screen's controls ** write straight SQL code to load the dataset ** use views in the database to load the dataset ** use stored procs to load the dataset

  • NHibernate and DTO / Viewmodel objects ** i typically use views when going down this route - I'll create a suite of views on top of my domain's schema, that denormalize the data into the model i need, and then use NH to load it up via a second set of maps

  • DTO / Automapper from domain model ** i don't like this approach unless I know that I already have everything from my domain model loaded in memory. i'll use a tool like Automapper to transfer data from my domain model into a DTO / ViewModel

i'm sure there are other options, but these are the three that i use most often, in order of how often i use them. they all have their own cost / benefits. but the important thing to understand is that you can and should retrieve the data in a manner that makes it easy for you to populate your screens.


I think people are missing the point of CQS (or CQRS, same thing really). CQR is simply a pattern to say that you should have separate models for read and writing. What those model are is completely up to your implementation requirements.

Folks that been talking about this recently usually describe extremely simple architectures and implementation to drive home that the fact that most enterprise software written today is over-designed and over-engineered.


One of the benefits of a CQRS ES approach is that you can devise really simple (read fast) view data. As a result of the event stream you can shape your read side data in any way you want. Hence lots of people like to de-normalise the data so that it is optimised for reading. You don't of course have to. But why wouldn't you? Think about the frequency of reads in a typical LOB compared to the writes.

Just in case you find it helpful and would like to see some code samples I have written a more detailed answer on my blog. You can find the post here: http://danielwhittaker.me/2014/10/05/build-master-details-view-using-cqrs-event-sourcing/