Separate read and write operations for better scalability and simpler code.
Code Snippet
// Commands (Write side)
public record CreateOrderCommand(string UserId, List Items);
public class CreateOrderHandler
{
private readonly IOrderRepository _repo;
public async Task Handle(CreateOrderCommand cmd)
{
var order = Order.Create(cmd.UserId, cmd.Items);
await _repo.SaveAsync(order);
return order.Id;
}
}
// Queries (Read side)
public record GetOrderSummaryQuery(string OrderId);
public class GetOrderSummaryHandler
{
private readonly IReadOnlyDbContext _db;
public async Task Handle(GetOrderSummaryQuery query)
{
return await _db.OrderSummaries
.Where(o => o.Id == query.OrderId)
.FirstOrDefaultAsync();
}
}
Why This Helps
- Optimized read models for queries
- Simpler command handlers with single responsibility
- Independent scaling of read/write workloads
How to Test
- Test commands and queries independently
- Verify read model consistency
When to Use
Complex domains, high-read workloads, event-sourced systems.
Performance/Security Notes
Start simple. Full CQRS with separate databases adds complexity. Use when justified.
References
Try this tip in your next project and share your results in the comments!
Discover more from Code, Cloud & Context
Subscribe to get the latest posts sent to your email.