Memoria

Integrate with ASP.NET Core Identity

Memoria’s EF Core store can share a DbContext with ASP.NET Core Identity, so user data and event-sourced aggregates live side by side in the same database, in the same transaction.

For the configuration surface, see Configuration: EF Core + Identity.

When to use this

If neither of these applies, the plain Memoria.EventSourcing.Store.EntityFrameworkCore package is simpler.

The shape

Your DbContext inherits from IdentityDomainDbContext instead of DomainDbContext. Everything else looks like a normal Memoria + EF Core setup:

public class ApplicationDbContext(
    DbContextOptions<DomainDbContext> options,
    TimeProvider timeProvider,
    IHttpContextAccessor httpContextAccessor)
    : IdentityDomainDbContext(options, timeProvider, httpContextAccessor)
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<ItemEntity> Items { get; set; } = null!;
}

services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

services
    .AddScoped(sp => new DbContextOptionsBuilder<DomainDbContext>()
        .UseSqlite(connectionString)
        .UseApplicationServiceProvider(sp)
        .Options);

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(configuration.GetConnectionString("DefaultConnection")));

services.AddMemoriaEntityFrameworkCore<ApplicationDbContext>();

IdentityDomainDbContext is IdentityDbContext with Memoria’s event-sourcing tables added in OnModelCreating. Migrations cover both sets of tables.

Combining writes in one transaction

Use the TrackAggregate / TrackEventEntities / Save extensions on IDomainDbContext to combine an event-sourced write with Identity changes:

await userManager.CreateAsync(newUser, password);

var trackAggregateResult = await dbContext.TrackAggregate(
    streamId, profileId, profile, expectedEventSequence: 0);

await dbContext.Save();

Both writes share the same EF Core transaction — either both commit or neither does.