触发公共交通消费者时启动新的 LifetimeScope

Start a new LifetimeScope when a Masstransit consumer is triggered

我们有以下代码来配置 recieveEndpoint:

private Action<IServiceBusReceiveEndpointConfigurator> GetReceiveEndpointConfigurator(IEnumerable<Type> consumerTypes)
{
    return c =>
        {
            c.EnableDeadLetteringOnMessageExpiration = true;
            c.SubscribeMessageTopics = false;
            c.MaxDeliveryCount = 3;
            c.EnableDeadLetteringOnMessageExpiration = true;
            c.UseRetry(Retry.Exponential(3, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(1)));
            foreach (var consumerType in consumerTypes)
            {
                c.Consumer(consumerType, p => _componentContext.Resolve(p));
            }
       };
}

一旦我们的应用程序启动,我们所有的消费者都会通过反射自动发现。我们有一个 DbContext 我们想在我们的许多消费者中使用。我们面临的问题是 DbContext 由于注册为 InstancePerLifetimeScope 而被处置。此处有更多详细信息:

两个建议来自这个post:

  1. DbContext 注册为 InstancePerDependency
  2. 在消费者中创建一个新的范围以开始一个新的LifetimeScope

第一个建议在我们的应用程序中不起作用,因为我们有一个 UnitOfWork 触发 DbContext 上的 SaveChangesAsync。结果将是 RepositoryUnitOfWork 将获得 DbContextSaveChangesAsync 的两个不同实例,因为 ChangeTracker 没有UnitOfWork 实现中的更改,但这些更改属于 Repository.

中的实例

第二个建议非常有效。在我的 Consumer 中,我创建了一个新的 LifetimeScope 并解析了我需要的组件:

public async Task Consume(ConsumeContext<RetailerCreatedEvent> context)
 {
     using (var scope = _serviceProvider.CreateScope())
     {
         var unitOfWork = scope.ServiceProvider.GetRequiredService<IUnitOfWork<MyDbContext>>();
     }
 }

有效,但看起来不太好。

有没有办法在 Consumer 触发之前开始一个新的 LifetimeScope?或者我应该重写我的 UnitOfWork 模式以确保在 RepositoriesUnitOfWork 中重复使用相同的 DbContext?

非常感谢您的建议

您需要使用 MassTransit.Autofac 包来解析您的消费者,这将使用 AutofacScopeProvider(包的一部分)来创建生命周期范围并解析您的消费者。

documentation 显示配置,包括如何通过扫描自动发现您的消费者并将他们添加到 MassTransit。

您的消费者不应该在使用此包的容器中包含任何容器代码,他们应该只添加 DbContext 作为构造函数依赖项并让 Autofac 完成工作。