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.
If neither of these applies, the plain Memoria.EventSourcing.Store.EntityFrameworkCore package is simpler.
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.
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.