将依赖项注入DBContext的正确方法

时间:2020-06-20 14:06:39

标签: c# asp.net-core .net-core entity-framework-core domain-driven-design

我正在尝试使用DDD和微服务方法创建一个项目,并且我对将域事件发送到另一个服务有一个小问题。我使用EF Core进行数据库通信,并使用MassTransit发送事件。

现在,我的DBConetxt中有一个重写的SaveChangesAsync方法,在该方法中,我通过使用MassTransit在Startup.cs中创建的总线发送了域事件。

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构造函数中,因此遇到了一些麻烦。例如,由于我的构造函数,我无法使用AddDbContext方法在Startup.cs文件中注册DbContext,所以我需要这样做:

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

我也想像AddDbContextPool那样使用池化DbContext。

所以我有2个问题:

  1. 如何在DbContext中正确注入依赖项?这是好事还是坏事?
  2. 从DbContext发送域事件是否是一种好方法?也许有更好的方法?

1 个答案:

答案 0 :(得分:0)

您做错了方法。我认为您必须将代码更正为:

public StudentsDbContext(DbContextOptions<OrderingContext> options, IBus bus) : base(options)
        {
            _bus = bus ?? throw new ArgumentNullException(nameof(bus));

        }

并在您的创业公司中:

services.AddDbContext<StudentsDbContext>(options =>
            {
                options.UseSqlServer(Configuration["ConnectionString"]);
            });