Pavas.Patterns.Cqrs
1.0.2
See the version list below for details.
dotnet add package Pavas.Patterns.Cqrs --version 1.0.2
NuGet\Install-Package Pavas.Patterns.Cqrs -Version 1.0.2
<PackageReference Include="Pavas.Patterns.Cqrs" Version="1.0.2" />
paket add Pavas.Patterns.Cqrs --version 1.0.2
#r "nuget: Pavas.Patterns.Cqrs, 1.0.2"
// Install Pavas.Patterns.Cqrs as a Cake Addin #addin nuget:?package=Pavas.Patterns.Cqrs&version=1.0.2 // Install Pavas.Patterns.Cqrs as a Cake Tool #tool nuget:?package=Pavas.Patterns.Cqrs&version=1.0.2
CQRS Design Pattern in .NET
Overview
The CQRS (Command Query Responsibility Segregation) pattern is a design pattern that separates the responsibilities of commands and queries in a system. Commands are used to modify the state, while queries are used to retrieve data. This separation leads to a more maintainable and scalable architecture.
Interfaces
Command Interfaces
- ICommandDispatcher: Dispatches commands to their respective handlers.
- ICommandHandler: Handles commands and optionally returns a result.
- ICommandHandlerAsync: An asynchronous version of
ICommandHandler
.
public interface ICommandDispatcher
{
Task<TValue> DispatchCommandAsync<TCommand, TValue>(TCommand command);
Task DispatchCommandAsync<TCommand>(TCommand command);
TValue DispatchCommand<TCommand, TValue>(TCommand command);
void DispatchCommand<TCommand>(TCommand command);
}
public interface ICommandHandler<in TCommand>
{
void Handle(TCommand command);
}
public interface ICommandHandler<in TCommand, out TResult>
{
TResult Handle(TCommand command);
}
public interface ICommandHandlerAsync<in TCommand>
{
Task HandleAsync(TCommand command, CancellationToken cancellationToken = new());
}
public interface ICommandHandlerAsync<in TCommand, TResult>
{
Task<TResult> HandleAsync(TCommand command, CancellationToken cancellationToken = new());
}
Query Interfaces
- IQueryDispatcher: Dispatches queries to their respective handlers.
- IQueryHandler: Handles queries and returns a result.
- IQueryHandlerAsync: An asynchronous version of IQueryHandler.
public interface IQueryDispatcher
{
Task<TValue> DispatchQueryAsync<TQuery, TValue>(TQuery query);
Task<TValue> DispatchQueryAsync<TValue>();
TValue DispatchQuery<TQuery, TValue>(TQuery query);
TValue DispatchQuery<TValue>();
}
public interface IQueryHandler<in TQuery, out TResult>
{
TResult Handle(TQuery query);
}
public interface IQueryHandler<out TResult>
{
TResult Handle();
}
public interface IQueryHandlerAsync<TResult>
{
Task<TResult> HandleAsync(CancellationToken cancellationToken = new());
}
public interface IQueryHandlerAsync<in TQuery, TResult>
{
Task<TResult> HandleAsync(TQuery query, CancellationToken cancellationToken = new());
}
Example Usage
Dispatching Queries
var queryDispatcher = serviceProvider.GetService<IQueryDispatcher>();
// Example async with query parameters
var resultWithParams = await queryDispatcher.DispatchAsync<SomeQuery, SomeResult>(new SomeQuery());
// Example async without query parameters
var resultWithoutParams = await queryDispatcher.DispatchAsync<SomeResult>()
// Example with query parameters
var resultWithParams = queryDispatcher.Dispatch<SomeQuery, SomeResult>(new SomeQuery());
// Example without query parameters
var resultWithoutParams = queryDispatcher.Dispatch<SomeResult>()
Dispatching Queries
var commandDispatcher = serviceProvider.GetService<ICommandDispatcher>();
// Example async with command response
var resultWithParams = await commandDispatcher.DispatchAsync<SomeCommand, SomeResult>(new SomeCommand());
// Example async without command response
await commandDispatcher.DispatchAsync<SomeCommand>(new SomeCommand())
// Example with command response
var resultWithParams = commandDispatcher.Dispatch<SomeCommand, SomeResult>(new SomeCommand());
// Example without command response
commandDispatcher.Dispatch<SomeCommand>(new SomeCommand())
Implementing Query Handlers
public class MyQueryHandler : IQueryHandlerAsync<SomeQuery, SomeResult>
{
public async Task<SomeResult> HandleAsync(SomeQuery query, CancellationToken cancellationToken = new())
{
// Handle the query and return the result
}
}
public class MyQueryHandler : IQueryHandler<SomeQuery, SomeResult>
{
public SomeResult Handle(SomeQuery query)
{
// Handle the query and return the result
}
}
Implementing Command Handlers
public class MyCommandHandler : ICommandHandlerAsync<SomeCommand, SomeResult>
{
public async Task<SomeResult> HandleAsync(SomeCommand command, CancellationToken cancellationToken = new())
{
// Handle the command and return the result (if any)
}
}
public class MyCommandHandler : ICommandHandler<SomeCommand, SomeResult>
{
public SomeResult Handle(SomeCommand command)
{
// Handle the command and return the result (if any)
}
}
Dependency Injection
var serviceCollection = new ServiceCollection();
// Register command handlers
serviceCollection.AddCommands();
// Register query handlers
serviceCollection.AddQueries();
var serviceProvider = serviceCollection.BuildServiceProvider();
Conclusion
The CQRS pattern provides a clear separation between commands and queries, making your application more maintainable and scalable. By implementing the interfaces and extension methods described above, you can easily integrate CQRS into your .NET applications.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Scrutor (>= 4.2.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.