CesarBotas.Database.Abstractions
1.11.0
dotnet add package CesarBotas.Database.Abstractions --version 1.11.0
NuGet\Install-Package CesarBotas.Database.Abstractions -Version 1.11.0
<PackageReference Include="CesarBotas.Database.Abstractions" Version="1.11.0" />
<PackageVersion Include="CesarBotas.Database.Abstractions" Version="1.11.0" />
<PackageReference Include="CesarBotas.Database.Abstractions" />
paket add CesarBotas.Database.Abstractions --version 1.11.0
#r "nuget: CesarBotas.Database.Abstractions, 1.11.0"
#:package CesarBotas.Database.Abstractions@1.11.0
#addin nuget:?package=CesarBotas.Database.Abstractions&version=1.11.0
#tool nuget:?package=CesarBotas.Database.Abstractions&version=1.11.0
botas-cqrs
Framework corporativo para .NET 10. CQRS com pipeline de behaviors, Result Pattern, migrations multi-banco, mensageria Kafka e RabbitMQ — tudo com observabilidade nativa.
Documentação
Botas.CQRS
| Documento | Descrição |
|---|---|
| Arquitetura (C4) | Modelos C4: Context, Container, Component e Code |
| Pacotes | Detalhamento de cada pacote NuGet |
| Uso em API | Guia de integração em projetos ASP.NET Core |
| Result Pattern | Guia completo do Result Pattern e tipos de erro |
| Pipeline Behaviors | Behaviors embutidos e como criar behaviors customizados |
| Publicação NuGet | Como compilar, versionar e publicar os pacotes |
| Guia para Juniores | Introdução ao CQRS e ao framework para devs iniciantes |
Botas.Database
| Documento | Descrição |
|---|---|
| Botas.Database | Migrations multi-banco, CLI, lock distribuído, histórico e auditoria |
Mensageria
| Documento | Descrição |
|---|---|
| Botas.Kafka | Kafka: producer, consumer, retry, DLQ, Avro, OpenTelemetry |
| Botas.Rabbit | RabbitMQ: publisher, consumer, retry, OpenTelemetry |
O que é CQRS?
CQRS (Command Query Responsibility Segregation) é um padrão que separa operações de escrita (Commands) de operações de leitura (Queries). Isso torna o código mais organizado, testável e fácil de manter.
┌─────────────────────────────────────────────────────────┐
│ Sua Aplicação │
│ │
│ Controller / Minimal API │
│ │ │
│ ▼ │
│ IDispatcher ◄── ponto único de entrada │
│ │ │
│ ┌─────┴──────┐ │
│ ▼ ▼ │
│ Command Query │
│ Handler Handler │
│ (escreve) (lê) │
└─────────────────────────────────────────────────────────┘
Pacotes
A solução é composta por 5 pacotes NuGet com responsabilidades bem definidas:
Botas.CQRS — pacote principal ⭐ recomendado
Pacote agregador. Inclui tudo: DI, assembly scanning, behaviors e dispatcher.
dotnet add package Botas.CQRS
Use quando: você está construindo uma API ou aplicação e quer tudo funcionando com uma linha de configuração.
builder.Services.AddBotasCQRS(options =>
{
options.AssembliesToScan.Add(typeof(Program).Assembly);
});
Botas.CQRS.Abstractions — contratos
Apenas interfaces e tipos base. Sem dependências externas.
dotnet add package Botas.CQRS.Abstractions
Use quando: você tem um projeto de domínio ou aplicação que precisa referenciar apenas os contratos, sem carregar a implementação.
Interfaces disponíveis:
| Namespace | Interface | Descrição |
|---|---|---|
Commands |
ICommand |
Comando sem retorno |
Commands |
ICommand<TResult> |
Comando com retorno |
Queries |
IQuery<TResult> |
Consulta com retorno |
Handlers |
ICommandHandler<TCommand> |
Handler de comando sem retorno |
Handlers |
ICommandHandler<TCommand, TResult> |
Handler de comando com retorno |
Handlers |
IQueryHandler<TQuery, TResult> |
Handler de consulta |
Notifications |
INotification |
Evento/notificação |
Notifications |
INotificationHandler<T> |
Handler de notificação |
Pipeline |
IPipelineBehavior<TRequest, TResult> |
Behavior de pipeline |
Dispatching |
IDispatcher |
Dispatcher central |
Validation |
IValidator<T> |
Validador |
Context |
IRequestContext |
Contexto da requisição |
Context |
ICorrelationContext |
Contexto de correlação |
Security |
ICurrentUser |
Usuário autenticado |
Transactions |
ITransactionCoordinator |
Coordenador de transações |
Time |
IDateTimeProvider |
Provedor de data/hora |
Botas.CQRS.Results — Result Pattern
Implementação do Result Pattern para evitar exceções em fluxos de negócio.
dotnet add package Botas.CQRS.Results
Use quando: você quer retornar sucesso ou falha de forma explícita, sem lançar exceções.
// Sucesso
Result<Guid> result = Result<Guid>.Ok(userId);
// Falha
Result<Guid> result = Result<Guid>.Fail(new NotFoundError("User", id.ToString()));
// Pattern matching
return result.Match(
onSuccess: id => Ok(new { id }),
onFailure: error => BadRequest(error.Message));
Tipos de erro disponíveis:
| Tipo | Código | Quando usar |
|---|---|---|
ValidationError |
validation.failed |
Campos inválidos na entrada |
DomainError |
domain.violation |
Regra de domínio violada |
BusinessError |
business.rule |
Regra de negócio violada |
NotFoundError |
not.found |
Recurso não encontrado |
UnauthorizedError |
unauthorized |
Acesso negado |
ConflictError |
conflict |
Conflito ou duplicidade |
InternalError |
internal.error |
Erro interno inesperado |
FieldError |
field.<nome> |
Erro em campo específico |
Botas.CQRS.Dispatching — dispatcher e pipeline
Implementação do IDispatcher, PipelineExecutor, HandlerResolver e NotificationPublisher.
dotnet add package Botas.CQRS.Dispatching
Use quando: você quer usar o dispatcher sem o bootstrap automático do pacote principal (cenários avançados).
Componentes:
| Classe | Responsabilidade |
|---|---|
Dispatcher |
Roteia comandos, queries e notificações |
PipelineExecutor |
Executa a cadeia de behaviors |
HandlerResolver |
Resolve handlers com cache de expression trees |
NotificationPublisher |
Publica notificações (sequencial ou paralelo) |
Botas.CQRS.Behaviors — pipeline behaviors
Behaviors prontos para uso no pipeline de requisições.
dotnet add package Botas.CQRS.Behaviors
Use quando: você quer usar os behaviors individualmente ou criar behaviors customizados baseados nos existentes.
Pipeline padrão (ordem de execução, de fora para dentro):
ExceptionBehavior ← captura exceções não tratadas
CorrelationBehavior ← propaga CorrelationId / TraceId
LoggingBehavior ← log de início e fim
PerformanceBehavior ← mede tempo (alerta > 500ms)
ValidationBehavior ← executa IValidator<T>
TransactionBehavior ← envolve em transação (se configurado)
AuditBehavior ← registra usuário + timestamp
Handler ← sua lógica de negócio
| Behavior | Dependências necessárias |
|---|---|
ExceptionBehavior |
ILogger |
CorrelationBehavior |
ICorrelationContext, IRequestContext |
LoggingBehavior |
ILogger, IRequestContext |
PerformanceBehavior |
ILogger |
ValidationBehavior |
IEnumerable<IValidator<T>> |
TransactionBehavior |
ITransactionCoordinator (opcional) |
AuditBehavior |
ILogger, ICurrentUser, IDateTimeProvider, IRequestContext |
Início rápido
1. Instalar
dotnet add package Botas.CQRS
2. Configurar
// Program.cs
builder.Services.AddBotasCQRS(options =>
{
options.AssembliesToScan.Add(typeof(Program).Assembly);
});
3. Criar um Command
// CreateUserCommand.cs
public sealed record CreateUserCommand(string Name, string Email) : ICommand<Result<Guid>>;
// CreateUserCommandHandler.cs
public sealed class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, Result<Guid>>
{
public async ValueTask<Result<Guid>> Handle(CreateUserCommand command, CancellationToken ct = default)
{
var id = Guid.NewGuid();
// salvar no banco...
return Result<Guid>.Ok(id);
}
}
4. Criar uma Query
// GetUserByIdQuery.cs
public sealed record GetUserByIdQuery(Guid UserId) : IQuery<Result<UserDto>>;
// GetUserByIdQueryHandler.cs
public sealed class GetUserByIdQueryHandler : IQueryHandler<GetUserByIdQuery, Result<UserDto>>
{
public async ValueTask<Result<UserDto>> Handle(GetUserByIdQuery query, CancellationToken ct = default)
{
var user = await _repository.GetByIdAsync(query.UserId, ct);
if (user is null)
return new NotFoundError("User", query.UserId.ToString());
return Result<UserDto>.Ok(new UserDto(user.Id, user.Name, user.Email));
}
}
5. Usar no Controller
[ApiController]
[Route("api/users")]
public sealed class UsersController(IDispatcher dispatcher) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Create(CreateUserRequest request, CancellationToken ct)
{
var result = await dispatcher.Execute<CreateUserCommand, Result<Guid>>(
new CreateUserCommand(request.Name, request.Email), ct);
return result.Match(
onSuccess: id => CreatedAtAction(nameof(GetById), new { id }, new { id }),
onFailure: error => BadRequest(error));
}
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id, CancellationToken ct)
{
var result = await dispatcher.Query<GetUserByIdQuery, Result<UserDto>>(
new GetUserByIdQuery(id), ct);
return result.Match(
onSuccess: dto => Ok(dto),
onFailure: error => error is NotFoundError ? NotFound() : BadRequest(error));
}
}
Opções de configuração
builder.Services.AddBotasCQRS(options =>
{
// Assemblies a escanear (obrigatório ao menos um)
options.AssembliesToScan.Add(typeof(Program).Assembly);
// Behaviors (todos habilitados por padrão)
options.EnableValidation = true;
options.EnableLogging = true;
options.EnablePerformance = true;
options.EnableTransactions = true;
options.EnableCorrelation = true;
options.EnableAudit = true;
// Notificações em paralelo (padrão: sequencial)
options.EnableParallelNotificationPublishing = false;
// Behaviors customizados
options.PipelineBehaviors.Add(typeof(MeuBehaviorCustomizado<,>));
});
Estrutura recomendada de projeto
src/
├── MinhaApi/ # Camada de apresentação
│ ├── Controllers/
│ └── Program.cs
├── MinhaApi.Application/ # Casos de uso
│ ├── Users/
│ │ ├── Commands/
│ │ │ └── CreateUser/
│ │ │ ├── CreateUserCommand.cs
│ │ │ ├── CreateUserCommandHandler.cs
│ │ │ └── CreateUserCommandValidator.cs
│ │ └── Queries/
│ │ └── GetUserById/
│ │ ├── GetUserByIdQuery.cs
│ │ └── GetUserByIdQueryHandler.cs
│ └── Notifications/
│ └── UserCreated/
│ ├── UserCreatedNotification.cs
│ └── SendWelcomeEmailHandler.cs
└── MinhaApi.Domain/ # Entidades e regras de domínio
Comparação com MediatR
| Característica | MediatR | Botas.CQRS |
|---|---|---|
| Target framework | .NET 6+ | .NET 10 |
| Result Pattern embutido | ❌ | ✅ |
| Behaviors prontos | ❌ | ✅ (7 behaviors) |
| Observabilidade (OpenTelemetry) | Parcial | ✅ nativo |
| Auditoria embutida | ❌ | ✅ |
| Correlação de requisições | ❌ | ✅ |
| Publicação paralela de notificações | ❌ | ✅ |
| Cache de delegates (expression trees) | ❌ | ✅ |
| Sem dependências externas (Abstractions) | ❌ | ✅ |
Todos os pacotes do ecossistema
CQRS
| Pacote | Descrição |
|---|---|
Botas.CQRS |
Pacote principal — bootstrap completo |
Botas.CQRS.Abstractions |
Contratos e interfaces |
Botas.CQRS.Results |
Result Pattern |
Botas.CQRS.Dispatching |
Dispatcher, pipeline, resolver |
Botas.CQRS.Behaviors |
7 behaviors prontos |
Database
| Pacote | Descrição |
|---|---|
Botas.Database |
Meta-pacote — todos os providers |
Botas.Database.Abstractions |
Contratos de migrations |
Botas.Database.Runner |
Engine de execução + CLI |
Botas.Database.PostgreSql |
Provider PostgreSQL |
Botas.Database.SqlServer |
Provider SQL Server |
Botas.Database.MySql |
Provider MySQL |
Botas.Database.Oracle |
Provider Oracle |
Mensageria
| Pacote | Descrição |
|---|---|
Botas.Kafka |
Kafka: producer, consumer, retry, DLQ, Avro |
Botas.Rabbit |
RabbitMQ via MassTransit |
Requisitos
- .NET 10.0+
- Microsoft.Extensions.DependencyInjection
- Microsoft.Extensions.Logging
Licença
Consulte o arquivo LICENSE.
| 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
- FluentMigrator (>= 6.2.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on CesarBotas.Database.Abstractions:
| Package | Downloads |
|---|---|
|
CesarBotas.Database.Extensions
Extensões de Dependency Injection para o framework Botas.Database. |
GitHub repositories
This package is not used by any popular GitHub repositories.