Cosmos.EventSourcing.Abstractions 0.0.10

There is a newer version of this package available.
See the version list below for details.
dotnet add package Cosmos.EventSourcing.Abstractions --version 0.0.10
                    
NuGet\Install-Package Cosmos.EventSourcing.Abstractions -Version 0.0.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cosmos.EventSourcing.Abstractions" Version="0.0.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cosmos.EventSourcing.Abstractions" Version="0.0.10" />
                    
Directory.Packages.props
<PackageReference Include="Cosmos.EventSourcing.Abstractions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cosmos.EventSourcing.Abstractions --version 0.0.10
                    
#r "nuget: Cosmos.EventSourcing.Abstractions, 0.0.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cosmos.EventSourcing.Abstractions@0.0.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cosmos.EventSourcing.Abstractions&version=0.0.10
                    
Install as a Cake Addin
#tool nuget:?package=Cosmos.EventSourcing.Abstractions&version=0.0.10
                    
Install as a Cake Tool

Cosmos.EventSourcing.Abstractions

NuGet

Abstracciones base para implementar Event Sourcing y CQRS en .NET 10.

Descripción

Este paquete proporciona las abstracciones fundamentales necesarias para construir aplicaciones usando Event Sourcing y el patrón CQRS (Command Query Responsibility Segregation). Define interfaces y clases base que permiten una arquitectura desacoplada y testeable.

Características

Event Sourcing

  • AggregateRoot: Clase base para agregados con manejo de eventos no confirmados
  • IEventStore: Interfaz para persistir y recuperar agregados desde el event store
    • AppendEvent: Agregar eventos a un stream
    • StartStream: Iniciar un nuevo stream para un agregado
    • SaveChangesAsync: Persistir los cambios de forma asíncrona
    • ExistsAsync<T>: Verificar si un agregado existe en el store (por Guid o string)
    • GetAggregateRootAsync<T>: Recuperar un agregado por ID, versión o timestamp

Command Side (CQRS)

  • ICommandHandler<TCommand>: Handler síncrono para comandos sin retorno
  • ICommandHandlerAsync<TCommand>: Handler asíncrono para comandos sin retorno
  • ICommandHandler<TCommand, TResult>: Handler síncrono con valor de retorno
  • ICommandHandlerAsync<TCommand, TResult>: Handler asíncrono con valor de retorno
  • ICommandRouter: Router para invocar command handlers

Query Side (CQRS)

  • IQueryHandler<TQuery, TResult>: Handler para consultas
  • IQueryRouter: Router para invocar query handlers
  • IProjectionStore: Almacén de proyecciones/vistas de lectura

Instalación

dotnet add package Cosmos.EventSourcing.Abstractions

Uso

Crear un Aggregate Root

using Cosmos.EventSourcing.Abstractions;

public class Order : AggregateRoot
{
    public List<OrderItem> Items { get; private set; } = new();
    public OrderStatus Status { get; private set; }

    public void AddItem(string productId, int quantity, decimal price)
    {
        var @event = new ItemAdded(Id, productId, quantity, price);
        Apply(@event);
        _uncommittedEvents.Add(@event);
    }

    private void Apply(ItemAdded @event)
    {
        Items.Add(new OrderItem(@event.ProductId, @event.Quantity, @event.Price));
    }
}

Implementar un Command Handler

using Cosmos.EventSourcing.Abstractions.Commands;

public record AddItemToOrder(string OrderId, string ProductId, int Quantity, decimal Price);

public class AddItemToOrderHandler : ICommandHandlerAsync<AddItemToOrder>
{
    private readonly IEventStore _eventStore;

    public AddItemToOrderHandler(IEventStore eventStore)
    {
        _eventStore = eventStore;
    }

    public async Task HandleAsync(AddItemToOrder command, CancellationToken cancellationToken)
    {
        var order = await _eventStore.GetAggregateRootAsync<Order>(
            command.OrderId,
            cancellationToken
        );

        order?.AddItem(command.ProductId, command.Quantity, command.Price);

        _eventStore.Save(order!);
        await _eventStore.SaveChangesAsync();
    }
}

Implementar un Query Handler

using Cosmos.EventSourcing.Abstractions.Queries;

public record GetOrderById(string OrderId);

public class GetOrderByIdHandler : IQueryHandler<GetOrderById, OrderDto?>
{
    private readonly IProjectionStore _projectionStore;

    public GetOrderByIdHandler(IProjectionStore projectionStore)
    {
        _projectionStore = projectionStore;
    }

    public async Task<OrderDto?> HandleAsync(GetOrderById query, CancellationToken cancellationToken)
    {
        return await _projectionStore.GetByIdAsync<OrderDto>(query.OrderId, cancellationToken);
    }
}

Usar el Command Router

public class OrderController
{
    private readonly ICommandRouter _commandRouter;

    public OrderController(ICommandRouter commandRouter)
    {
        _commandRouter = commandRouter;
    }

    public async Task<IActionResult> AddItem(AddItemRequest request)
    {
        var command = new AddItemToOrder(
            request.OrderId,
            request.ProductId,
            request.Quantity,
            request.Price
        );

        await _commandRouter.InvokeAsync(command, CancellationToken.None);

        return Ok();
    }
}

Patrones de Event Sourcing

Verificar Existencia de un Agregado

// Verificar si existe por string ID
bool exists = await _eventStore.ExistsAsync<Order>("order-123", cancellationToken);

// Verificar si existe por Guid
bool exists = await _eventStore.ExistsAsync<Order>(Guid.Parse("..."), cancellationToken);

if (!exists)
    throw new NotFoundException("Order not found");

Recuperar Agregados por Versión

// Obtener el estado actual
var order = await _eventStore.GetAggregateRootAsync<Order>("order-123", ct);

// Obtener el estado en una versión específica
var orderV5 = await _eventStore.GetAggregateRootAsync<Order>("order-123", version: 5, ct);

// Obtener el estado en un momento específico
var orderAtTime = await _eventStore.GetAggregateRootAsync<Order>(
    "order-123",
    DateTimeOffset.Parse("2024-01-15T10:00:00Z"),
    ct
);

Implementaciones Concretas

Este paquete solo contiene abstracciones. Para implementaciones listas para usar:

Requisitos

  • .NET 10.0 o superior

Dependencias

  • Cosmos.EventDriven.Abstractions — para IPublicEventSender e IPrivateEventSender en el aggregate root

Licencia

Copyright © Cosmos. Todos los derechos reservados.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.12 72 3/12/2026
0.0.11 40 3/12/2026
0.0.10 35 3/12/2026
0.0.10-RC.2 60 3/11/2026
0.0.10-RC.1 46 3/10/2026
0.0.9 174 2/24/2026
0.0.8 507 2/23/2026
0.0.7 656 2/11/2026
0.0.6 80 2/11/2026
0.0.5 262 12/3/2025
0.0.4 688 12/3/2025
0.0.3 211 11/25/2025
0.0.1 398 9/19/2025