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
aggregateTypeTypeThe aggregate type to construct.
streamIdGuidThe aggregate's stream id.
fromVersionlong?Ignored. Rebuilding always starts from the beginning of the stream, or from the latest snapshot at or below
toVersion, because an aggregate rebuilt from a later version alone would lack the state its earlier events established. Kept for source compatibility.toVersionlong?Inclusive end version, or
nullfor stream head.cancellationTokenCancellationTokenPropagated to the read-store query.
Returns
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
streamIdGuidThe aggregate's stream id.
fromVersionlong?Ignored. Rebuilding always starts from the beginning of the stream, or from the latest snapshot at or below
toVersion, because an aggregate rebuilt from a later version alone would lack the state its earlier events established. Kept for source compatibility.toVersionlong?Inclusive end version, or
nullfor stream head.cancellationTokenCancellationTokenPropagated to the read-store query.
Returns
- Task<TAggregate>
The reconstructed aggregate, or
nullif the stream does not exist.
Type Parameters
TAggregateThe aggregate type — must have a parameterless constructor.