Table of Contents

Class EfCoreAggregateDataSource

Namespace
Savvyio.Extensions.EFCore.Domain
Assembly
Savvyio.Extensions.EFCore.Domain.dll

Provides an implementation of the EfCoreDataSource that is optimized for Domain Driven Design and the concept of Aggregate Root.

public class EfCoreAggregateDataSource : EfCoreDataSource, IDisposable, IEfCoreDataSource, IDataSource, IUnitOfWork
Inheritance
EfCoreAggregateDataSource
Implements
Derived
Inherited Members

Examples

EfCoreAggregateDataSource<TContext> is the domain-scoped EF Core data source that implements IEfCoreDataSource and restricts context usage to aggregate root operations. Subclass it with the specific DbContext type to provide a named aggregate context factory. The example wires up a minimal aggregate context and confirms it resolves from the data source.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Savvyio.Domain;
using Savvyio.Extensions.EFCore;
using Savvyio.Extensions.EFCore.Domain;

namespace ExampleApp;

public sealed class OrderingWorkflow
{
    public async Task<int> SaveOrderAsync()
    {
        var dispatcher = new RecordingDomainEventDispatcher();
        var source = new OrderingDataSource(dispatcher, new EfCoreDataSourceOptions
        {
            ContextConfigurator = builder => builder.EnableDetailedErrors(),
            ModelConstructor = modelBuilder => modelBuilder.Entity<OrderAggregate>().HasKey(order => order.Id)
        });

        var repository = new EfCoreAggregateRepository<OrderAggregate, Guid>(source);
        repository.Add(OrderAggregate.Place(Guid.NewGuid(), "PO-2048"));

        await source.SaveChangesAsync();
        return dispatcher.Published.Count;
    }
}

public sealed class OrderingDataSource : EfCoreAggregateDataSource
{
    public OrderingDataSource(IDomainEventDispatcher dispatcher, EfCoreDataSourceOptions options) : base(dispatcher, options)
    {
    }
}

public sealed class RecordingDomainEventDispatcher : IDomainEventDispatcher
{
    public List<IDomainEvent> Published { get; } = new();

    public void Raise(IDomainEvent request)
    {
        Published.Add(request);
    }

    public Task RaiseAsync(IDomainEvent request, Action<Cuemon.Threading.AsyncOptions>? setup = null)
    {
        Published.Add(request);
        return Task.CompletedTask;
    }
}

public sealed class OrderAggregate : Aggregate<Guid, IDomainEvent>, IAggregateRoot<IDomainEvent, Guid>
{
    private OrderAggregate()
    {
    }

    private OrderAggregate(Guid id, string orderNumber) : base(id)
    {
        OrderNumber = orderNumber;
        AddEvent(new OrderPlaced(orderNumber));
    }

    public string OrderNumber { get; private set; } = string.Empty;

    public static OrderAggregate Place(Guid id, string orderNumber)
    {
        return new OrderAggregate(id, orderNumber);
    }
}

public sealed record OrderPlaced(string OrderNumber) : DomainEvent;

Constructors

EfCoreAggregateDataSource(IDomainEventDispatcher, DbContext)

Initializes a new instance of the EfCoreAggregateDataSource class.

protected EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, DbContext dbContext)

Parameters

dispatcher IDomainEventDispatcher

The IDomainEventDispatcher that are responsible for raising domain events.

dbContext DbContext

The DbContext to associate with this data store.

EfCoreAggregateDataSource(IDomainEventDispatcher, EfCoreDataSourceOptions)

Initializes a new instance of the EfCoreAggregateDataSource class.

public EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, EfCoreDataSourceOptions options)

Parameters

dispatcher IDomainEventDispatcher

The IDomainEventDispatcher that are responsible for raising domain events.

options EfCoreDataSourceOptions

The EfCoreDataSourceOptions used to configure this instance.

Methods

SaveChangesAsync(Action<AsyncOptions>)

Saves the different IRepository<TEntity, TKey> implementations as one transaction towards a data store asynchronous.

public override Task SaveChangesAsync(Action<AsyncOptions> setup = null)

Parameters

setup Action<AsyncOptions>

The AsyncOptions which may be configured.

Returns

Task

A Task that represents the asynchronous operation.

Remarks

Will, just before SaveChangesAsync(CancellationToken) is called, extract and call RaiseAsync(IDomainEvent, Action<AsyncOptions>) for all aggregate roots contained within the backing DbContext.

See Also