dotnet-cqrs/docs/tutorials/modular-solution/03-cqrs-layer.md

142 lines
3.5 KiB
Markdown

# CQRS Layer
Implement commands, queries, and handlers.
## Create Command
```csharp
// OrderManagement.CQRS/Commands/PlaceOrderCommand.cs
namespace OrderManagement.CQRS.Commands;
public record PlaceOrderCommand
{
public int CustomerId { get; init; }
public List<OrderItemDto> Items { get; init; } = new();
}
public record OrderItemDto
{
public int ProductId { get; init; }
public string ProductName { get; init; } = string.Empty;
public int Quantity { get; init; }
public decimal Price { get; init; }
}
```
## Command Handler
```csharp
// OrderManagement.CQRS/Commands/PlaceOrderCommandHandler.cs
using Svrnty.CQRS.Abstractions;
using OrderManagement.Domain.Entities;
namespace OrderManagement.CQRS.Commands;
public class PlaceOrderCommandHandler : ICommandHandler<PlaceOrderCommand, int>
{
private readonly IOrderRepository _repository;
public PlaceOrderCommandHandler(IOrderRepository repository)
{
_repository = repository;
}
public async Task<int> HandleAsync(PlaceOrderCommand command, CancellationToken ct)
{
var items = command.Items.Select(i => new OrderItem
{
ProductId = i.ProductId,
ProductName = i.ProductName,
Quantity = i.Quantity,
Price = i.Price
}).ToList();
var order = Order.Create(command.CustomerId, items);
await _repository.AddAsync(order, ct);
await _repository.SaveChangesAsync(ct);
return order.Id;
}
}
```
## Validator
```csharp
// OrderManagement.CQRS/Validators/PlaceOrderCommandValidator.cs
using FluentValidation;
namespace OrderManagement.CQRS.Validators;
public class PlaceOrderCommandValidator : AbstractValidator<PlaceOrderCommand>
{
public PlaceOrderCommandValidator()
{
RuleFor(x => x.CustomerId).GreaterThan(0);
RuleFor(x => x.Items).NotEmpty();
RuleForEach(x => x.Items).ChildRules(item =>
{
item.RuleFor(x => x.ProductId).GreaterThan(0);
item.RuleFor(x => x.Quantity).GreaterThan(0);
item.RuleFor(x => x.Price).GreaterThan(0);
});
}
}
```
## Query
```csharp
// OrderManagement.CQRS/Queries/GetOrderQuery.cs
public record GetOrderQuery
{
public int OrderId { get; init; }
}
public record OrderDto
{
public int Id { get; init; }
public int CustomerId { get; init; }
public string Status { get; init; } = string.Empty;
public decimal TotalAmount { get; init; }
public DateTimeOffset PlacedAt { get; init; }
public List<OrderItemDto> Items { get; init; } = new();
}
```
## Query Handler
```csharp
// OrderManagement.CQRS/Queries/GetOrderQueryHandler.cs
public class GetOrderQueryHandler : IQueryHandler<GetOrderQuery, OrderDto>
{
private readonly IOrderRepository _repository;
public async Task<OrderDto> HandleAsync(GetOrderQuery query, CancellationToken ct)
{
var order = await _repository.GetByIdAsync(query.OrderId, ct);
return new OrderDto
{
Id = order.Id,
CustomerId = order.CustomerId,
Status = order.Status.ToString(),
TotalAmount = order.TotalAmount,
PlacedAt = order.PlacedAt,
Items = order.Items.Select(i => new OrderItemDto
{
ProductId = i.ProductId,
ProductName = i.ProductName,
Quantity = i.Quantity,
Price = i.Price
}).ToList()
};
}
}
```
## Next Steps
Continue to [DAL Layer](04-dal-layer.md)