In the previous two posts, I showed some simple patterns for commands and command handlers. Now let’s talk about the other half of the story: queries!
- Brownfield CQRS part 1 – Commands
- Brownfield CQRS part 2 – Command Handlers
- Brownfield CQRS part 3 – Queries, Parameters and Results
- Brownfield CQRS part 4 – Command Dispatcher
On our WCF service, each query method:
- Returns one or more QueryResult objects — a DTO created exclusively for this query.
- Takes a QueryParameter argument — if required, a DTO containing search criteria, paging options etc.
For example, to query for bookings:
[ServiceContract]
public interface IBookingService
{
[OperationContract]
IEnumerable<BookingQueryResult> SearchBookings(
BookingSearchParameters parameters);
}
Query Parameters
Queries take simple DTO parameter objects just like commands. They carry both search criteria (what to look for) and things like paging options (how to return results). They can also define defaults. For example:
[DataContract]
public class BookingSearchParameters
{
public BookingSearchParameters()
{
// default values
NumberOfResultsPerPage = 10;
Page = 1;
}
[DataMember]
public Tuple<DateTime, DateTime> Period { get; set; }
[DataMember]
public int NumberOfResultsPerPage { get; set; }
[DataMember]
public int PageNumber { get; set; }
}
Query Object
Queries are then executed by a query object — an application service that queries your ORM, reporting store, or domain + automapper (if you’re still using a single model internally for commands and queries).
public interface IQuery<TParameters, TResult>
{
public TResult Execute(TParameters parameters);
}
Query Results
Queries can return a single result (e.g. to look up the details of a specify item), or a sequence (searching):
public class BookingSearchQuery :
IQuery<BookingSearchParameters, IEnumerable<BookingSearchResult>>
{
public IEnumerable<BookingSearchResult> Execute(
BookingSearchParameters parameters)
{
...
}
}
Query results are simple DTOs that provide all the information the client needs.
[DataContract]
public class BookingSearchResult
{
[DataMember]
public string PartyName { get; set; }
[DataMember]
public int PartySize { get; set; }
[DataMember]
public DateTime TimeAndDay { get; set; }
[DataMember]
public string SpecialRequests { get; set; }
}
Query Results should be able to be rendered directly on the UI, in one query. If the they require further mapping, or multiple calls (e.g. to get different aspects of an object) before you can use it on a view model, then they are most likely:
- Too granular — query results should be big flattened/denormalized objects which contain everything you need in one hit.
- Based on the wrong model (the domain or persistence model) — they should be based on the UI’s needs, and present a screenful of information per call.
As with commands, having a one-to-one mapping between query objects and queries makes it easy to add/remove functionality to a system.
Can’t I use the same object for sending commands and returning results?
That BookingSearchResult looks more or less identical to BookTableCommand we sent before — it has all the same properties. That doesn’t seem very DRY! Can’t I just create a generic DTO and use that in both cases?
Using the same class for commands and queries is called CRUD, and it leads to exactly the sort of situations we are trying to avoid — where commands needs to use different representations of objects than when querying, but can’t because they are tightly coupled to share the same object. As I said in part 1, commands are driven by business transactions, but queries are driven by UX needs, and often include projections, flattening and aggregation — more than just 1:1 mapping.
Next: Part 4 – Command Dispatcher
June 16, 2010



9 Comments
seagile on June 17, 2010 at 9:54 am.
I have found WCF Data Services (a.k.a. OData Services) to be invaluable in case of querying the viewmodel. There is virtually no effort required, truly a technology that fits the bill. No ServiceContracts, nor datacontracts, nor tedious mapping code between some intermediate model or plain old ado.net data reader. It’s just fine to use ADO.NET EF in this case. Paging, sorting, filtering are all built-in and you can use LINQ for query type-safety.
On the client I tend to use a ViewModel (what was queried plus what the user entered) to Command mapper. Again, you can use existing solutions such as Automapper for that purpose. For command validation I use FluentValidation, before shipping off the command to the server.
Simon Brangwin on June 24, 2010 at 3:45 am.
Hi Richard,
I noticed that both your query service method and command method (in part 1) use the same service contract interface, IBookingService.
Am I missing something or should the Commands and Query methods be on 2 separate service contracts to keep a clear segregation between them? Or is this not necessary and having them live in the one WCF service is fine?
Richard on June 24, 2010 at 9:21 am.
Simon: I was hoping no one would mention that :)
I’m not so confident about whether to use one combined or two separate command/query service endpoints at this stage. Have gone with one for now, for simplicity and simplicity for clients (they shouldn’t care if we’re using CQRS internally). Interested to hear other opinions however.
Fred Wang on August 11, 2010 at 11:16 am.
Hi Rachard,
One or two WCF service is a tough decision.
You had already list the advantage for one WCF service.
But since the repositorys for C and Q are diff,so if I need to have two repositorys in this WCF service,CommandRepository and QueryRepository.
Maybe you can decide it in runtime,but if you ask IOC to create the Repository,two Repositorys are necessary.
My english is poor,forgive me!
Fred Wang on August 19, 2010 at 2:49 am.
And an other question.If we use WCF,we can’t use ORM(NH) to fetch QueryResult, NH entity is hard to transfer.
How to handle it?
Richard on August 19, 2010 at 9:24 am.
@Fred: with CQRS you would likely have a persistent view model/read model containing big flattened DTO objects that contain everything about those objects a client might need.
Fred Wang on August 25, 2010 at 9:27 am.
@Richard
Thanks.
Pingback: Richard Dingwall » Brownfield CQRS part 2 – Command Handlers
HuntSoul on August 6, 2011 at 1:15 am.
Hey,Rechard,the flattened DTO objects?Do you mean the object that don’t have dependency but simple properties?