Class EfCoreTracedAggregateRepository<TEntity, TKey>
- Namespace
- Savvyio.Extensions.EFCore.Domain.EventSourcing
- Assembly
- Savvyio.Extensions.EFCore.Domain.EventSourcing.dll
Provides an implementation of the EfCoreRepository<TEntity, TKey> that is optimized for Domain Driven Design and Event Sourcing.
public class EfCoreTracedAggregateRepository<TEntity, TKey> : ITracedAggregateRepository<TEntity, TKey>, IReadableRepository<TEntity, TKey>, IWritableRepository<TEntity, TKey>, IRepository<TEntity, TKey> where TEntity : class, IEntity<TKey>, ITracedAggregateRoot<TKey>
Type Parameters
TEntityThe type of the entity that implements the ITracedAggregateRoot<TKey> interface.
TKeyThe type of the key that uniquely identifies the entity.
- Inheritance
-
EfCoreTracedAggregateRepository<TEntity, TKey>
- Implements
-
ITracedAggregateRepository<TEntity, TKey>IReadableRepository<TEntity, TKey>IWritableRepository<TEntity, TKey>IRepository<TEntity, TKey>
- Derived
Examples
EfCoreTracedAggregateRepository<TAggregateRoot, TKey, TContext> stores and loads event-sourced aggregates by writing and reading individual traced domain event rows. The setup requires a context configured with ModelBuilder.AddEventSourcing, an IMarshaller for event serialization, and the aggregate type with RegisterDelegates implemented. The example creates a repository, appends an event, and rehydrates the aggregate from stored events.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Savvyio;
using Savvyio.Domain.EventSourcing;
using Savvyio.Extensions.EFCore;
using Savvyio.Extensions.EFCore.Domain.EventSourcing;
using Savvyio.Handlers;
namespace ExampleApp;
public sealed class EventSourcingWorkflow
{
public Task<OrderTimeline> LoadAsync(Guid id)
{
var source = new EfCoreDataSource(new EfCoreDataSourceOptions
{
ContextConfigurator = builder => builder.EnableDetailedErrors(),
ModelConstructor = modelBuilder => modelBuilder.AddEventSourcing<OrderTimeline, Guid>()
});
var repository = new EfCoreTracedAggregateRepository<OrderTimeline, Guid>(source, new SimpleMarshaller());
repository.Add(new OrderTimeline(id, "PO-8001"));
return repository.GetByIdAsync(id);
}
}
public sealed class OrderTimeline : TracedAggregateRoot<Guid>
{
public OrderTimeline(Guid id, string orderNumber) : base()
{
AddEvent(new OrderPlaced(id, orderNumber));
}
private OrderTimeline(Guid id, IEnumerable<ITracedDomainEvent> events) : base(id, events)
{
}
public string OrderNumber { get; private set; } = string.Empty;
protected override void RegisterDelegates(IFireForgetRegistry<ITracedDomainEvent> handler)
{
handler.Register<OrderPlaced>(e =>
{
Id = e.OrderId;
OrderNumber = e.OrderNumber;
});
}
}
public sealed record OrderPlaced(Guid OrderId, string OrderNumber) : TracedDomainEvent;
public sealed class SimpleMarshaller : IMarshaller
{
public Stream Serialize<TValue>(TValue value)
{
return new MemoryStream(JsonSerializer.SerializeToUtf8Bytes(value));
}
public Stream Serialize(object value, Type inputType)
{
return new MemoryStream(JsonSerializer.SerializeToUtf8Bytes(value, inputType));
}
public TValue Deserialize<TValue>(Stream data)
{
return JsonSerializer.Deserialize<TValue>(data)!;
}
public object Deserialize(Stream data, Type returnType)
{
return JsonSerializer.Deserialize(data, returnType)!;
}
}
Constructors
EfCoreTracedAggregateRepository(IEfCoreDataSource, IMarshaller)
Initializes a new instance of the EfCoreTracedAggregateRepository<TEntity, TKey> class.
public EfCoreTracedAggregateRepository(IEfCoreDataSource source, IMarshaller marshaller)
Parameters
sourceIEfCoreDataSourceThe IEfCoreDataSource that handles actual I/O communication with a source of data.
marshallerIMarshallerThe IMarshaller that is used when converting between ITracedDomainEvent and arbitrary data.
Methods
Add(TEntity)
Marks the specified entity to be added in the data store when SaveChangesAsync(Action<AsyncOptions>) is called.
public void Add(TEntity entity)
Parameters
entityTEntityThe aggregate to add.
AddRange(IEnumerable<TEntity>)
Marks the specified entities to be added in the data store when SaveChangesAsync(Action<AsyncOptions>) is called.
public void AddRange(IEnumerable<TEntity> entities)
Parameters
entitiesIEnumerable<TEntity>The aggregates to add.
GetByIdAsync(TKey, Action<AsyncOptions>)
Loads an aggregate from the specified id asynchronous.
public Task<TEntity> GetByIdAsync(TKey id, Action<AsyncOptions> setup = null)
Parameters
idTKeyThe key that uniquely identifies the aggregate.
setupAction<AsyncOptions>The AsyncOptions which may be configured.
Returns
- Task<TEntity>
A Task<TResult> that represents the asynchronous operation. The task result either contains the entity of the operation or
nullif not found.
Exceptions
- MissingMethodException
TEntitydoes not have a suitable constructor.