# 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 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 { private readonly IOrderRepository _repository; public PlaceOrderCommandHandler(IOrderRepository repository) { _repository = repository; } public async Task 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 { 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 Items { get; init; } = new(); } ``` ## Query Handler ```csharp // OrderManagement.CQRS/Queries/GetOrderQueryHandler.cs public class GetOrderQueryHandler : IQueryHandler { private readonly IOrderRepository _repository; public async Task 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)