Explanation for when to handle domain events may be incorrect?
- Dominant language
- C#
- Stars
- 10.9k
- Forks
- 3.8k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 4
Description
In the `OrderingContext` class there is the following method:
```csharp
public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default)
{
// Dispatch Domain Events collection.
// Choices:
// A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including
// side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime
// B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions.
// You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers.
await _mediator.DispatchDomainEventsAsync(this);
// After executing this line all the changes (from the Command Handler and Domain Event Handlers)
// performed through the DbContext will be committed
_ = await base.SaveChangesAsync(cancellationToken);
return true;
}
```
I'm wondering if the explanation in the comments of this method is correct, given that the commands are handled through a PipelineBehavior `TransactionBehavior`, which has the following `Handle` method:
```csharp
public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken)
{
...
try
{
...
await strategy.ExecuteAsync(async () =>
{
Guid transactionId;
await using var transaction = await _dbContext.BeginTransactionAsync();
using (_logger.BeginScope(new List> { new("TransactionContext", transaction.TransactionId) }))
{
...
response = await next();
...
await _dbContext.CommitTransactionAsync(transaction);
transactionId = transaction.TransactionId;
}
await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync(transactionId);
});
return response;
}
catch (Exception ex)
{
...
throw;
}
}
```
And, as explained in the [EF Core docs](https://learn.microsoft.com/en-us/ef/core/saving/transactions#controlling-transactions), using the `BeginTransactionAsync` method makes that any subsequent call to `SaveChangesAsync` becomes part of the same transaction.
So, in this situation, it wouldn't matter whether `await _mediator.DispatchDomainEventsAsync(this);` was called before or after `await base.SaveChangesAsync(cancellationToken);`, right? Or what am I misunderstanding / missing?
Contributor guide
Assessment
This issue has not been assessed yet.