Entity Framework Core Domain and Integration event dispatch.
-
Construct a EntityFrameworkEventDispatcherContext class by passing in the DbContext itself, and an implementation of IEventDispatcher.
-
Override the following SaveChanges() and SaveChangesAsync() methods with the example code below (or roll your own).
-
Include the ClearEvents() and GetEventDispatcherContext() methods if required.
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
IEventDispatcherContext dispatcherContext = GetEventDispatcherContext();
DispatchEvents<IDomainEvent>(dispatcherContext);
int returnCode = base.SaveChanges(acceptAllChangesOnSuccess);
DispatchEvents<IIntegrationEvent>(dispatcherContext);
ClearEvents();
return returnCode;
}
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
IEventDispatcherContext dispatcherContext = GetEventDispatcherContext();
await dispatcherContext.DispatchAsync<IDomainEvent>(dispatcherContext, cancellationToken).ConfigureAwait(false);
int returnCode = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken).ConfigureAwait(false);
await dispatcherContext.DispatchAsync<IIntegrationEvent>(dispatcherContext, cancellationToken).ConfigureAwait(false);
ClearEvents();
return returnCode;
}
private void ClearEvents()
{
foreach (EntityEntry<IEventObject> eventObject in this.ChangeTracker.Entries<IEventObject>())
{
eventObject.Entity.EventStore.ClearEvents();
}
}
private IEventDispatcherContext GetEventDispatcherContext()
{
return new EntityFrameworkEventDispatcherContext(this, this.GetService<IEventDispatcher>());
}
- Add the IEventObject interface to any of your DbContext entities.
- This will require you to implement the IEventStore interface.
- The following example will demonstrate.
public class User : IEntity
{
public User()
{
EventStore = new EventStore();
}
public IEventStore EventStore { get; }
}
- To add a domain event, create a class which derives from IDomainEvent and you can add that to your eventstore on the entity.
- Integration events should follow IIntegrationEvent.
- You can create your own event types and use them as you wish. Dispatch them at your chosen point in the SaveChanges() or SaveChangesAsync() methods.
-
When save changes is called any event dispatch handlers registered will handle that event.
-
Your handlers should derive from the following interface to picked up by the IEventDispatcher:
- IEventDispatchHandler<MyDomainEvent>
-
See the link to a sample project below, which should demonstrate clearly.
See https://github.com/TheDanielDoyle/EventDispatcher.EntityFrameworkCore/blob/develop/Samples/EventDispatcher.EntityFrameworkCore.Samples.InMemory/SampleDbContext.cs for an example DbContext implementation, which uses the EntityFrameworkEventDispatcherContext.