CQRSharp.Core
4.0.3
See the version list below for details.
dotnet add package CQRSharp.Core --version 4.0.3
NuGet\Install-Package CQRSharp.Core -Version 4.0.3
<PackageReference Include="CQRSharp.Core" Version="4.0.3" />
<PackageVersion Include="CQRSharp.Core" Version="4.0.3" />
<PackageReference Include="CQRSharp.Core" />
paket add CQRSharp.Core --version 4.0.3
#r "nuget: CQRSharp.Core, 4.0.3"
#:package CQRSharp.Core@4.0.3
#addin nuget:?package=CQRSharp.Core&version=4.0.3
#tool nuget:?package=CQRSharp.Core&version=4.0.3
CQRSharp
A lightweight, extensible, and attribute-driven Command Query Responsibility Segregation (CQRS) framework for .NET applications, with complete Native AOT support.
A Roslyn source generator wires up dispatching and registration at compile time, so there is no runtime reflection and the whole framework is trimming- and Native-AOT-friendly.
For more information, see the CQRSharp project page.
Features
- Native AOT & trimming-safe — a Roslyn source generator wires up all dispatch and registration at compile time; zero runtime reflection.
- Attribute-driven — define commands, queries, streaming requests, and notifications with simple marker interfaces and handlers.
- One façade — dispatch everything through
ICqrsDispatcher(Send/Stream/Publish). - Build-time analyzers — catch missing handlers, the wrong dispatch method, and mis-wired pipeline exemptions as you type (CQRA diagnostics), with code fixes.
- Opt-in pipeline behaviors — validation, resilience/retries, timeouts, rate limiting, idempotency, unit-of-work, and logging, composed order-insensitively through the fluent
AddCqrsGenerated(b => ...)builder (UseValidation(),UseResilience(...),UseOutbox(...),UseIdempotency(...), …). - Reliable messaging — a background task queue and a transactional outbox with at-least-once delivery and distributed-tracing propagation.
- Batteries-included persistence — drop-in in-memory, Redis (
CQRSharp.Redis), and EF Core (CQRSharp.EntityFrameworkCore) stores for both the outbox and request idempotency; no hand-written atomic-claim code required. - Fail-fast configuration — a startup validator surfaces silent mis-wiring (an outbox with no store, a non-transactional unit of work, outbox-bypassing notifications, or an
IIdempotentRequest/IRetryableRequestmarker whose behavior was never enabled) as loud errors at host start instead of at first request. - Introspection — a diagnostics API and health checks that describe exactly how each request is bound.
Installation
dotnet add package CQRSharp
The CQRSharp meta-package pulls in the abstractions, core runtime, and the source generator for a plug-and-play setup.
On projects with ImplicitUsings enabled (the .NET 8+ default) it also ships global usings for the authoring
surface, so the snippets below need no using directives — CommandBase, ICommandHandler<>, CommandResult,
ICqrsDispatcher, AddCqrsGenerated, and friends are already in scope. (Opt out with
<CQRSharpImplicitUsings>false</CQRSharpImplicitUsings>.)
For durable outbox and idempotency persistence, add the integration package for your backing store (the core package ships in-memory stores for development and single-node use out of the box):
dotnet add package CQRSharp.Redis # Redis-backed outbox + idempotency stores (Native-AOT-compatible)
dotnet add package CQRSharp.EntityFrameworkCore # EF Core (relational) outbox + idempotency stores
Quick Start
Register CQRSharp on your host. AddCqrsGenerated is emitted by the source generator and wires up every discovered
handler:
services.AddCqrsGenerated();
Define a command and its handler:
public sealed class CreateUser : CommandBase
{
public required string Name { get; init; }
}
public sealed class CreateUserHandler : ICommandHandler<CreateUser>
{
public Task<CommandResult> Handle(CreateUser command, CancellationToken ct)
=> Task.FromResult(CommandResult.FromSuccess());
}
Dispatch it through the single injected façade, ICqrsDispatcher:
public sealed class UsersController(ICqrsDispatcher dispatcher)
{
public Task Create(string name)
=> dispatcher.Send(new CreateUser { Name = name });
}
Queries derive from QueryBase<TResult> and are handled by IQueryHandler<TQuery, TResult>; streaming requests are
dispatched with dispatcher.Stream, and notifications implement INotification and are published with
dispatcher.Publish. Use CommandBase<TContext> / QueryBase<TResult, TContext> when a request needs a custom
context.
Order-insensitive wiring
Cross-cutting behaviors and stores are opt-in and can be composed in any order through the fluent overload of
AddCqrsGenerated. The builder applies them in the correct sequence, so registration order never matters and a missing
store is reported at startup rather than at first request:
services.AddCqrsGenerated(builder => builder
.UseValidation()
.UseOutbox(o => o.UseInMemoryStore()) // dev/test; swap the store for o.UseRedis(...) or o.UseEntityFrameworkCore<TContext>()
.ValidateOnStart());
The outbox and idempotency are each enabled in one cohesive step that selects the mode and registers the store, e.g.
UseOutbox(o => o.Transactional().UseEntityFrameworkCore<MyDbContext>()) or UseIdempotency(i => i.UseRedis(connectionString)).
For durable persistence, add the integration package for your backing store (CQRSharp.Redis or
CQRSharp.EntityFrameworkCore) and choose its store verb inside UseOutbox / UseIdempotency.
Contributing
Contributions are welcome! Please open issues and pull requests for bug fixes, enhancements, or new features.
To contribute:
- Fork the repository.
- Create a new branch.
- Make your changes.
- Submit a pull request.
Please ensure that your code follows the project's coding standards and includes appropriate tests.
License
This project is licensed under the MIT License.
Note: This project is in active development.
| 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. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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
- CQRSharp.Abstractions (>= 4.0.3)
- Microsoft.Extensions.DependencyInjection (>= 9.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 9.0.2)
- Microsoft.Extensions.Hosting (>= 9.0.2)
- Microsoft.Extensions.Logging.Console (>= 9.0.2)
-
net8.0
- CQRSharp.Abstractions (>= 4.0.3)
- Microsoft.Extensions.DependencyInjection (>= 9.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 9.0.2)
- Microsoft.Extensions.Hosting (>= 9.0.2)
- Microsoft.Extensions.Logging.Console (>= 9.0.2)
-
net9.0
- CQRSharp.Abstractions (>= 4.0.3)
- Microsoft.Extensions.DependencyInjection (>= 9.0.2)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 9.0.2)
- Microsoft.Extensions.Hosting (>= 9.0.2)
- Microsoft.Extensions.Logging.Console (>= 9.0.2)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on CQRSharp.Core:
| Package | Downloads |
|---|---|
|
CQRSharp
A lightweight, attribute-driven CQRS framework for .NET 8/9/10 with first-class Native AOT support. A Roslyn source generator wires up command, query, stream, and notification dispatch at compile time — no runtime reflection — and bundled analyzers catch wiring mistakes as you type. Install this meta-package for the full plug-and-play setup: abstractions, runtime, source generator, and analyzers. |
|
|
CQRSharp.Pipelines
Optional, opt-in pipeline behaviors for CQRSharp — validation, unit of work, resilience/retries, timeouts, rate limiting, idempotency, and logging — plus a one-call pipeline-pack registration for sensible defaults. |
|
|
CQRSharp.Redis
A 100% Native-AOT-clean Redis integration for CQRSharp. Its first feature is a durable IOutboxStore that persists outbox messages as discrete Redis hash fields (binary payloads stored verbatim) and runs all claim, lease, and finalize logic as atomic server-side Lua, so two processors never claim the same message and crashed claimants are reclaimed after a visibility timeout. It also provides a durable IIdempotencyStore that rejects duplicate requests via atomic set-if-not-exists claims with a server-side expiry window. |
|
|
CQRSharp.EntityFrameworkCore
An Entity Framework Core integration for CQRSharp. Its first feature is a durable IOutboxStore backed by a DbContext: atomic claim with an optimistic-concurrency visibility lease, persisted retry/back-off and dead-lettering. It also provides a durable IIdempotencyStore backed by a keyed table with an optimistic-concurrency claim and a retention window. EF Core uses runtime query compilation, so this package is not Native-AOT or full-trim compatible. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version 4.0.3. Multi-assembly setup is now zero-config: the generated AddCqrsGenerated entry points are internal, so there is no "composition root" to designate and test projects / layered apps just work (no more cross-assembly CS0121). RunMode.Queued now fails fast with a clear error when no running host has started the queue consumer, instead of hanging.