AlJawad.DefaultCQRS
1.0.8
dotnet add package AlJawad.DefaultCQRS --version 1.0.8
NuGet\Install-Package AlJawad.DefaultCQRS -Version 1.0.8
<PackageReference Include="AlJawad.DefaultCQRS" Version="1.0.8" />
<PackageVersion Include="AlJawad.DefaultCQRS" Version="1.0.8" />
<PackageReference Include="AlJawad.DefaultCQRS" />
paket add AlJawad.DefaultCQRS --version 1.0.8
#r "nuget: AlJawad.DefaultCQRS, 1.0.8"
#:package AlJawad.DefaultCQRS@1.0.8
#addin nuget:?package=AlJawad.DefaultCQRS&version=1.0.8
#tool nuget:?package=AlJawad.DefaultCQRS&version=1.0.8
AlJawad.DefaultCQRS
A powerful and scalable CQRS library for .NET applications.
Table of Contents
Introduction
AlJawad.DefaultCQRS is a .NET library that provides a ready-to-use implementation of the Command Query Responsibility Segregation (CQRS) pattern. It's designed to be highly generic and scalable, allowing you to quickly build robust and maintainable applications.
The library offers a set of default commands and queries for common CRUD operations, as well as support for caching, validation, and a unit of work. This allows you to focus on your business logic instead of writing boilerplate code.
Key Benefits
- Reduce Boilerplate Code: The library provides a set of generic commands, queries, and handlers that can be used for any entity. This eliminates the need to write repetitive code for basic CRUD operations.
- Scalability: By separating read and write operations, CQRS allows you to scale each side of your application independently. This library is designed to support this scalability.
- Flexibility: The library is highly customizable. You can easily extend the default commands and queries or create your own to meet your specific needs.
- Testability: The separation of concerns in CQRS makes it easier to test your application's business logic.
- Getting Started
Getting Started
Installation
To install the library, you can use the .NET CLI:
dotnet add package AlJawad.DefaultCQRS
Configuration
Configuring the AlJawad.DefaultCQRS library involves two main steps: initializing the library's services and configuring your entities.
1. Initialize the Library
First, you need to call the InitializeDefaultCQRS extension method in your Program.cs file. This method sets up the necessary model binders for the library.
// In Program.cs
#region required for Default CQRS
builder.Services.InitializeDefaultCQRS();
#endregion
2. Configure Your Entities
For each entity you want to use with the library, you'll need to call the AddEntityDynamicConfiguration extension method. This method registers the default command and query handlers for your entity.
Here's an example of how to configure a Product entity:
// In Program.cs
#region required for Default CQRS
builder.Services.AddEntityDynamicConfiguration<Product, int, CreateProductDto, UpdateProductDto, ProductDto, ProductAuthorizationHandler>(builder.Configuration);
#endregion
In this example:
Productis the entity class.intis the type of the entity's primary key.CreateProductDtois the data transfer object (DTO) for creating a new product.UpdateProductDtois the DTO for updating an existing product.ProductDtois the DTO for reading a product.ProductAuthorizationHandleris the authorization handler for theProductentity.
You will also need to configure the database connection string in your appsettings.json file.
Usage
Once you've configured the library, you can use the IMediator interface to send commands and queries.
Commands
The library provides a set of default commands for common CRUD operations.
Create
To create a new entity, you can send an EntityCreateCommand.
var command = new EntityCreateCommand<CreateProductDto, Response<ProductDto>>(createProductDto);
var response = await _mediator.Send(command);
Update
To update an existing entity, you can send an EntityUpdateCommand.
var command = new EntityUpdateCommand<int, UpdateProductDto, Response<ProductDto>>(productId, updateProductDto);
var response = await _mediator.Send(command);
Delete
To delete an entity, you can send an EntityDeleteCommand.
var command = new EntityDeleteCommand<int, Response<ProductDto>>(productId);
var response = await _mediator.Send(command);
Queries
The library also provides a set of default queries for reading data.
Get by ID
To retrieve an entity by its ID, you can send an EntityIdentifierQuery.
var query = new EntityIdentifierQuery<int, Response<ProductDto>>(productId);
var response = await _mediator.Send(query);
Get a List
To retrieve a list of entities, you can send an EntityListQuery.
var query = new EntityListQuery<ResponseArray<ProductDto>>();
var response = await _mediator.Send(query);
Get a Paged List
To retrieve a paged list of entities, you can send an EntityPagedQuery.
var query = new EntityPagedQuery<ResponseList<ProductDto>>(pageNumber, pageSize);
var response = await _mediator.Send(query);
Advanced Topics
Validation
The library uses FluentValidation to validate commands. This is handled by the ValidateEntityModelCommandBehavior, which is automatically registered when you configure your entities.
You can create validators for your command DTOs, and they will be automatically applied. For example, to create a validator for the CreateProductDto, you would create a class that inherits from BaseValidator<CreateProductDto, Product, long, ProductDto>.
Here's an example of a validator for the CreateProductDto:
public class ProductCreateValidator : BaseValidator<CreateProductDto, Product, long, ProductDto>
{
public ProductCreateValidator(IUnitOfWork unitOfWork, IDistributedCache cache)
: base(unitOfWork, cache)
{
var _repository = unitOfWork.Set<Product>();
RuleFor(x => x.Name).NotNull().NotEmpty().WithMessage("Required");
RuleFor(x => x.Price).NotNull().WithMessage("Required");
RuleFor(e => e).Custom((p, context) =>
{
var alreadyExist = _repository.FirstOrDefault(x => x.Name == p.Name);
if (alreadyExist != null)
{
context.AddFailure(new ValidationFailure("Name", "Already Existed"));
}
});
}
}
Unit of Work
The library uses the Unit of Work pattern to ensure that all database operations within a single command are transactional. The UnitOfWork class is automatically registered with the dependency injection container and can be injected into your command handlers.
Custom Handlers
If you need to implement custom logic for a specific command, you can create your own handler by inheriting from one of the default handler classes. For example, to create a custom handler for the EntityCreateCommand, you would create a class that inherits from EntityCreateCommandHandler.
Here's an example of a custom handler for creating a Category entity:
public class CategoryCreateCommandHandler : EntityCreateCommandHandler<IUnitOfWork, Category, int, CreateCategoryDto, CategoryDto>
{
public CategoryCreateCommandHandler(ILoggerFactory loggerFactory,
IUnitOfWork dataContext,
IMapper mapper,
IHttpContextAccessor context,
IDistributedCache cache,
IServiceProvider provider)
: base(loggerFactory, dataContext, mapper, context, cache, provider)
{
}
protected override async Task<Response<CategoryDto>> ProcessAsync(EntityCreateCommand<CreateCategoryDto, Response<CategoryDto>> request, CancellationToken cancellationToken)
{
// Implement your custom logic here.
// For example, you can add additional validation, logging, or other business logic.
return await base.ProcessAsync(request, cancellationToken);
}
}
Once you've created your custom handler, you need to configure it in your Program.cs file using the WithCreateHandler method:
builder.Services.AddEntityDynamicConfiguration<Category, int, CreateCategoryDto, UpdateCategoryDto, CategoryDto, CategoryAuthorizationHandler>(builder.Configuration)
.WithCreateHandler<CategoryCreateCommandHandler>()
.SkipUpdateValidator(false);//TO skip the validation
| 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
- AlJawad.SqlDynamicLinker (>= 1.0.8)
- AutoMapper (>= 14.0.0)
- DataTables.AspNetCore.Mvc (>= 1.4.2)
- FluentValidation (>= 11.11.0)
- MassTransit (>= 8.3.6)
- MediatR (>= 12.4.1)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 10.0.0-preview.1.25120.3)
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.0-preview.1.25080.5)
- Microsoft.Extensions.Identity.Core (>= 10.0.0-preview.1.25120.3)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.