Skip to main content
Table of Contents

Interface IAggregationService

Namespace
Stratara.Abstractions.EventSourcing
Assembly
Stratara.Abstractions.dll

Reconstructs an aggregate by reading its event stream + applying events. Command handlers and sagas use this — never read aggregates from projection views.

public interface IAggregationService
Extension Methods

Examples

Rehydrate an aggregate in a command handler, then apply a mutation:

public sealed class ShipOrderHandler(IAggregationService aggregator, IEventSource events)
    : ICommandHandler<ShipOrder>
{
    public async Task HandleAsync(ShipOrder command, CancellationToken cancellationToken)
    {
        var order = await aggregator.AggregateAsync<Order>(command.OrderId, cancellationToken: cancellationToken)
            ?? throw new InvalidOperationException($"Order {command.OrderId} not found.");

        await events.AppendAsync<Order>(order.Id, new OrderShipped(order.Id, DateTimeOffset.UtcNow),
            cancellationToken);
        await events.SaveChangesAsync(cancellationToken);
    }
}

Remarks

Tenant ownership: handlers operating on ITenantAggregates should prefer the AggregateOwnedByTenantAsync<TAggregate>(IAggregationService, Guid, Guid, CancellationToken) extension, which returns null on either "not found" or "wrong tenant" — the handler can then map both to NotFound without leaking foreign-tenant existence.

Methods

AggregateAsync(Type, Guid, long?, long?, CancellationToken)

Reflection-based variant for when the aggregate type is known only at runtime (replay tooling, generic admin endpoints).

Task<object?> AggregateAsync(Type aggregateType, Guid streamId, long? fromVersion = null, long? toVersion = null, CancellationToken cancellationToken = default)

Parameters

aggregateType Type

The aggregate type to construct.

streamId Guid

The aggregate's stream id.

fromVersion long?

Inclusive start version, or null for stream start.

toVersion long?

Inclusive end version, or null for stream head.

cancellationToken CancellationToken

Propagated to the read-store query.

Returns

Task<object>

The reconstructed aggregate, or null if the stream does not exist.

AggregateAsync<TAggregate>(Guid, long?, long?, CancellationToken)

Reconstruct an aggregate of TAggregate from streamId's event stream.

Task<TAggregate?> AggregateAsync<TAggregate>(Guid streamId, long? fromVersion = null, long? toVersion = null, CancellationToken cancellationToken = default) where TAggregate : notnull, new()

Parameters

streamId Guid

The aggregate's stream id.

fromVersion long?

Inclusive start version, or null for stream start.

toVersion long?

Inclusive end version, or null for stream head.

cancellationToken CancellationToken

Propagated to the read-store query.

Returns

Task<TAggregate>

The reconstructed aggregate, or null if the stream does not exist.

Type Parameters

TAggregate

The aggregate type — must have a parameterless constructor.