Я пытаюсь создать проект, используя подход DDD и микросервис, и у меня есть небольшой вопрос об отправке событий домена в другой сервис. Я использую EF Core для связи с базой данных и MassTransit для отправки событий.
Прямо сейчас у меня есть переопределенный метод SaveChangesAsyn c в моем DBConetxt, где я отправляю событие домена через шину, которую я создал в Startup.cs, используя MassTransit.
DBContext:
private readonly IBus _bus;
public StudentsDbContext(DbContextOptions options, IBus bus) : base(options)
{
_bus = bus;
}
...
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
var aggregates = ChangeTracker.Entries<IAggregateRoot>().ToList();
foreach (var aggregate in aggregates)
{
foreach (var domainEvent in aggregate.Entity.DomainEvents)
{
await _bus.Publish(domainEvent, domainEvent.GetType(), cancellationToken);
}
aggregate.Entity.ClearEvents();
}
return await base.SaveChangesAsync(cancellationToken);
}
Как видите, мне нужно вставить IBus
в конструктор DbContext, и из-за этого у меня возникли проблемы. Например, я не могу зарегистрировать свой DbContext в файле Startup.cs с помощью метода AddDbContext
из-за моего конструктора, поэтому мне нужно сделать это следующим образом:
services.AddSingleton<IBus>(bus);
services.AddTransient<StudentsDbContext>(provider =>
{
var options = new DbContextOptionsBuilder()
.UseSqlServer(Configuration.GetConnectionString("Default"))
.Options;
return new StudentsDbContext(options, provider.GetService<IBus>());
});
Из-за этого у меня проблемы с миграциями.
Unable to create an object of type 'StudentsDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
А также я хочу использовать объединенный DbContext, например, с AddDbContextPool
.
Итак, у меня есть 2 вопроса:
- Как правильно ввести зависимость в DbContext? Это хорошая или плохая практика?
- Это вообще хороший подход - отправлять события домена из DbContext? Может есть способ получше?