SolTechnology.Core.CQRS
0.8.0
dotnet add package SolTechnology.Core.CQRS --version 0.8.0
NuGet\Install-Package SolTechnology.Core.CQRS -Version 0.8.0
<PackageReference Include="SolTechnology.Core.CQRS" Version="0.8.0" />
<PackageVersion Include="SolTechnology.Core.CQRS" Version="0.8.0" />
<PackageReference Include="SolTechnology.Core.CQRS" />
paket add SolTechnology.Core.CQRS --version 0.8.0
#r "nuget: SolTechnology.Core.CQRS, 0.8.0"
#:package SolTechnology.Core.CQRS@0.8.0
#addin nuget:?package=SolTechnology.Core.CQRS&version=0.8.0
#tool nuget:?package=SolTechnology.Core.CQRS&version=0.8.0
Overview
The SolTechnology.Core.CQRS library provides a complete CQRS (Command Query Responsibility Segregation) implementation with an in-house mediator, Result pattern for explicit success/failure handling, automatic FluentValidation, fire-and-forget notifications, and logging pipeline behaviors.
Registration
services.AddCQRS();
// Or with explicit assembly scanning and options:
services.AddCQRS(
o => o.UseFluentValidation = true,
typeof(Program).Assembly);
Defining a Command
// Command with no return data (side-effect only)
public class CreateUserCommand : ICommand
{
public string Name { get; set; }
public string Email { get; set; }
}
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand>
{
public async Task<Result> Handle(CreateUserCommand command, CancellationToken cancellationToken)
{
await _userRepository.Create(command.Name, command.Email);
return Result.Success();
}
}
// Command with return data
public class CreateOrderCommand : ICommand<int>
{
public string Product { get; set; }
}
public class CreateOrderCommandHandler : ICommandHandler<CreateOrderCommand, int>
{
public async Task<Result<int>> Handle(CreateOrderCommand command, CancellationToken cancellationToken)
{
var orderId = await _orderRepository.Create(command.Product);
return Result<int>.Success(orderId);
}
}
Defining a Query
public class GetUserQuery : IQuery<User>
{
public int UserId { get; set; }
}
public class GetUserQueryHandler : IQueryHandler<GetUserQuery, User>
{
public async Task<Result<User>> Handle(GetUserQuery query, CancellationToken cancellationToken)
{
var user = await _userRepository.GetById(query.UserId);
if (user == null)
return Result<User>.Fail(new NotFoundError { Message = "User not found" });
return user;
}
}
Validation
Register a FluentValidation validator — failures are returned as Result.Fail(ValidationError) automatically. The handler is never invoked.
public class CreateUserCommandValidator : AbstractValidator<CreateUserCommand>
{
public CreateUserCommandValidator()
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
RuleFor(x => x.Email).NotEmpty().EmailAddress();
}
}
Notifications
Fire-and-forget events dispatched to all registered handlers. Each handler runs on its own background task with a fresh DI scope. Failures are isolated and logged — they never propagate to the caller and never stop other handlers.
public class UserCreated : INotification
{
public int UserId { get; set; }
}
public class SendWelcomeEmailHandler : INotificationHandler<UserCreated>
{
public async Task Handle(UserCreated notification, CancellationToken cancellationToken)
{
await _emailService.SendWelcome(notification.UserId);
}
}
// Publishing (returns immediately)
_mediator.Publish(new UserCreated { UserId = 42 });
Result Pattern
var result = await _mediator.Send(new GetUserQuery { UserId = 1 });
if (result.IsSuccess)
{
var user = result.Data;
}
else
{
var error = result.Error;
}
// Combinators
var output = await _mediator.Send(new GetUserQuery { UserId = 1 })
.Map(user => user.Name)
.Ensure(name => name.Length > 0, new Error { Message = "Empty name" });
For multi-step orchestration, see Story.md.
Pipeline Behaviors
Custom behaviors can be registered to wrap every request:
public class MyBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken ct)
{
// before
var response = await next();
// after
return response;
}
}
Built-in behaviors (registered automatically):
- LoggingPipelineBehavior — tracks every request as a logical operation with structured logging and OpenTelemetry spans.
- FluentValidationPipelineBehavior — runs all validators; short-circuits with
ValidationErroron failure.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FluentValidation (>= 11.11.0)
- FluentValidation.DependencyInjectionExtensions (>= 11.11.0)
- Microsoft.Extensions.Configuration (>= 10.0.1)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.1)
- Microsoft.Extensions.DependencyInjection (>= 10.0.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- Microsoft.Extensions.Options (>= 10.0.1)
- SolTechnology.Core.Logging (>= 1.1.1)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on SolTechnology.Core.CQRS:
| Package | Downloads |
|---|---|
|
SolTechnology.Core.Api
ASP.NET Core API utilities: RFC 7807 ProblemDetails error pipeline, header-based API versioning, MVC filters that auto-convert Result<T> to wire format. One-call AddApiCore + AddApiCoreFilters + UseSwaggerWithVersioning bootstrap. CorrelationId propagation through Core.Logging. |
|
|
SolTechnology.Core.Flow
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.