dotnet-cqrs/README.md

199 lines
11 KiB
Markdown

> This project was originally initiated by [Powered Software Inc.](https://poweredsoft.com/) and was forked from the [PoweredSoft.CQRS](https://github.com/PoweredSoft/CQRS) Repository
# CQRS
Our implementation of query and command responsibility segregation (CQRS).
## Getting Started
> Install nuget package to your awesome project.
| Package Name | NuGet | NuGet Install |
|-----------------------------------------| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------------------------------------------------------:|
| Svrnty.CQRS | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS/) | ```dotnet add package Svrnty.CQRS ``` |
| Svrnty.CQRS.MinimalApi | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.MinimalApi.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.MinimalApi/) | ```dotnet add package Svrnty.CQRS.MinimalApi ``` |
| Svrnty.CQRS.AspNetCore | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.AspNetCore.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.AspNetCore/) | ```dotnet add package Svrnty.CQRS.AspNetCore ``` |
| Svrnty.CQRS.FluentValidation | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.FluentValidation.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.FluentValidation/) | ```dotnet add package Svrnty.CQRS.FluentValidation ``` |
| Svrnty.CQRS.DynamicQuery | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.DynamicQuery.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery/) | ```dotnet add package Svrnty.CQRS.DynamicQuery ``` |
| Svrnty.CQRS.DynamicQuery.AspNetCore | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.DynamicQuery.AspNetCore.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery.AspNetCore/) | ```dotnet add package Svrnty.CQRS.DynamicQuery.AspNetCore ``` |
| Svrnty.CQRS.Grpc | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.Grpc.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.Grpc/) | ```dotnet add package Svrnty.CQRS.Grpc ``` |
> Abstractions Packages.
| Package Name | NuGet | NuGet Install |
| ---------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -----------------------------------------------------: |
| Svrnty.CQRS.Abstractions | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.Abstractions.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.Abstractions/) | ```dotnet add package Svrnty.CQRS.Abstractions ``` |
| Svrnty.CQRS.AspNetCore.Abstractions | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.AspNetCore.Abstractions.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.AspNetCore.Abstractions/) | ```dotnet add package Svrnty.CQRS.AspNetCore.Abstractions ``` |
| Svrnty.CQRS.DynamicQuery.Abstractions | [![NuGet](https://img.shields.io/nuget/v/Svrnty.CQRS.DynamicQuery.Abstractions.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/Svrnty.CQRS.DynamicQuery.Abstractions/) | ```dotnet add package Svrnty.CQRS.AspNetCore.Abstractions ``` |
## Sample of startup code for Minimal API (Recommended)
```csharp
var builder = WebApplication.CreateBuilder(args);
// Register CQRS core services
builder.Services.AddSvrntyCQRS();
builder.Services.AddDefaultCommandDiscovery();
builder.Services.AddDefaultQueryDiscovery();
// Add your commands and queries
AddQueries(builder.Services);
AddCommands(builder.Services);
// Add Swagger (optional)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
// Map CQRS endpoints - automatically creates routes for all commands and queries
app.MapSvrntyCommands(); // Creates POST /api/command/{commandName} endpoints
app.MapSvrntyQueries(); // Creates POST/GET /api/query/{queryName} endpoints
app.Run();
```
## Sample of startup code for ASP.NET Core MVC (Legacy)
```csharp
public void ConfigureServices(IServiceCollection services)
{
// make sure to add your queries and commands before configuring MvcBuilder with .AddSvrntyCommands and .AddSvrntyQueries
AddQueries(services);
AddCommands(services);
// adds the non related to aspnet core features.
services.AddSvrntyCQRS();
services
.AddControllers()
.AddSvrntyQueries() // adds queries to aspnetcore mvc.(you can make it configurable to load balance only commands on a instance)
.AddSvrntyCommands() // adds commands to aspnetcore mvc. (you can make it configurable to load balance only commands on a instance)
.AddFluentValidation();
services.AddSwaggerGen();
}
```
## Sample of startup code for gRPC
```csharp
var builder = WebApplication.CreateBuilder(args);
// Register CQRS core services
builder.Services.AddSvrntyCQRS();
builder.Services.AddDefaultCommandDiscovery();
builder.Services.AddDefaultQueryDiscovery();
// Add your commands and queries
AddQueries(builder.Services);
AddCommands(builder.Services);
// Add gRPC support
builder.Services.AddSvrntyCqrsGrpc();
var app = builder.Build();
// Map gRPC endpoints
app.MapSvrntyGrpcCommands();
app.MapSvrntyGrpcQueries();
app.Run();
```
### Important: protobuf-net Requirements for gRPC
To use gRPC, your commands and queries must be annotated with protobuf-net attributes:
```csharp
using ProtoBuf;
[ProtoContract]
public class CreatePersonCommand
{
[ProtoMember(1)]
public string FirstName { get; set; } = string.Empty;
[ProtoMember(2)]
public string LastName { get; set; } = string.Empty;
[ProtoMember(3)]
public int Age { get; set; }
}
[ProtoContract]
public class Person
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string FullName { get; set; } = string.Empty;
}
```
**Notes:**
- Add `[ProtoContract]` to each command/query/result class
- Add `[ProtoMember(n)]` to each property with sequential numbers starting from 1
- These attributes don't interfere with JSON serialization or FluentValidation
- You can use both HTTP REST (MinimalApi/MVC) and gRPC simultaneously
> Example how to add your queries and commands.
```csharp
private void AddCommands(IServiceCollection services)
{
services.AddCommand<CreatePersonCommand, CreatePersonCommandHandler>();
services.AddTransient<IValidator<CreatePersonCommand>, CreatePersonCommandValidator>();
services.AddCommand<EchoCommand, string, EchoCommandHandler>();
services.AddTransient<IValidator<EchoCommand>, EchoCommandValidator>();
}
private void AddQueries(IServiceCollection services)
{
services.AddQuery<PersonQuery, IQueryable<Person>, PersonQueryHandler>();
}
```
# Fluent Validation
We use fluent validation in all of our projects, but we don't want it to be enforced.
If you install ```Svrnty.CQRS.FluentValidation``` you can use this way of registrating your commands.
```csharp
public void ConfigureServices(IServiceCollection services)
{
// without Package.
services.AddCommand<EchoCommand, string, EchoCommandHandler>();
services.AddTransient<IValidator<EchoCommand>, EchoCommandValidator>();
}
public void ConfigureServices(IServiceCollection services)
{
// with Svrnty.CQRS.FluentValidation package.
services.AddCommand<EchoCommand, string, EchoCommandHandler, EchoCommandValidator>();
}
```
# 2024-2025 Roadmap
| Task | Description | Status |
|----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------|
| Support .NET 8 | Ensure compatibility with .NET 8. | ✅ |
| Support .NET 10 | Upgrade to .NET 10 with C# 14 language support. | ✅ |
| Update FluentValidation | Upgrade FluentValidation to version 11.x for .NET 10 compatibility. | ✅ |
| Add gRPC Support with protobuf-net | Implement gRPC endpoints with binary protobuf serialization for high-performance scenarios. | ✅ |
| Create a new demo project as an example | Develop a new demo project to serve as an example for users. | ⬜️ |
| New Independent Module for MVC | Develop a standalone module, independent of MVC, to enhance framework flexibility. | ⬜️ |
| Implement .NET Native Compilation (AOT) | Enable full Ahead-of-Time (AOT) compilation support (blocked by third-party dependencies). | ⬜️ |
| Create a website for the Framework | Develop a website to host comprehensive documentation for the framework. | ⬜️ |
| Re-add support for GraphQL | Re-integrate support for GraphQL, exploring lightweight solutions. | ⬜️ |