Part of DKNet.EfCore.Events. Evaluate [RaisesEvent] rules before the write, then map qualifying payloads from the entity after a successful save.
Use the console-project setup in the Quick Start, then replace Program.cs with this example.
using Microsoft.EntityFrameworkCore;
using DKNet.EfCore.Hooks;
using Microsoft.Extensions.DependencyInjection;
using var connection = new Microsoft.Data.Sqlite.SqliteConnection("Data Source=:memory:");
connection.Open();
var services = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
services.AddLogging();
services.AddDbContextWithHook<DemoDb>(o => o.UseSqlite(connection));
services.AddSingleton<MapsterMapper.IMapper, MapsterMapper.Mapper>();
services.AddEventPublisher<DemoDb, ConsolePublisher>();
using var provider = services.BuildServiceProvider();
using var scope = provider.CreateScope();
await using var db = scope.ServiceProvider.GetRequiredService<DemoDb>();
await db.Database.EnsureCreatedAsync();
db.Add(new Item { Name = "Coffee" });
await db.SaveChangesAsync(); // ItemPayload { Id = 1, Name = Coffee }
public sealed class DemoDb(DbContextOptions<DemoDb> options) : DbContext(options)
{
public DbSet<Item> Items => Set<Item>();
}
[DKNet.EfCore.Abstractions.Events.RaisesEvent(typeof(ItemPayload),
DKNet.EfCore.Abstractions.Events.EventOperations.Created)]
public sealed class Item
{
public int Id { get; set; }
public string Name { get; set; } = "";
}
public sealed record ItemPayload
{
public int Id { get; set; }
public string Name { get; set; } = "";
}
public sealed class ConsolePublisher : DKNet.EfCore.Abstractions.Events.DefaultEventPublisher
{
public override Task PublishAsync(object value, CancellationToken cancellationToken = default)
{
Console.WriteLine(value);
return Task.CompletedTask;
}
}
The example demonstrates the runtime type-naming form with a hand-written payload and no generator. In a generator-enabled domain project, declare that payload as a [GenerateDto] partial record from the same entity. Convention forms require DtoGenerator to emit the composed payload name.
Declaration forms and defaults live in Declare events for persistence operations. Runtime registration is the same as queued-event publishing.
Abstractions owns the declaration, DtoGenerator validates and can generate the payload, and Hooks supplies the save phases. This package decides which declarations qualify and publishes the resulting mapped objects.