触发公共交通消费者时启动新的 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:
- 将
DbContext
注册为 InstancePerDependency
- 在消费者中创建一个新的范围以开始一个新的
LifetimeScope
第一个建议在我们的应用程序中不起作用,因为我们有一个 UnitOfWork 触发 DbContext
上的 SaveChangesAsync
。结果将是 Repository
和 UnitOfWork
将获得 DbContext
和 SaveChangesAsync
的两个不同实例,因为 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 模式以确保在 Repositories
和 UnitOfWork
中重复使用相同的 DbContext?
非常感谢您的建议
您需要使用 MassTransit.Autofac
包来解析您的消费者,这将使用 AutofacScopeProvider(包的一部分)来创建生命周期范围并解析您的消费者。
documentation 显示配置,包括如何通过扫描自动发现您的消费者并将他们添加到 MassTransit。
您的消费者不应该在使用此包的容器中包含任何容器代码,他们应该只添加 DbContext 作为构造函数依赖项并让 Autofac 完成工作。
我们有以下代码来配置 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:
- 将
DbContext
注册为InstancePerDependency
- 在消费者中创建一个新的范围以开始一个新的
LifetimeScope
第一个建议在我们的应用程序中不起作用,因为我们有一个 UnitOfWork 触发 DbContext
上的 SaveChangesAsync
。结果将是 Repository
和 UnitOfWork
将获得 DbContext
和 SaveChangesAsync
的两个不同实例,因为 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 模式以确保在 Repositories
和 UnitOfWork
中重复使用相同的 DbContext?
非常感谢您的建议
您需要使用 MassTransit.Autofac
包来解析您的消费者,这将使用 AutofacScopeProvider(包的一部分)来创建生命周期范围并解析您的消费者。
documentation 显示配置,包括如何通过扫描自动发现您的消费者并将他们添加到 MassTransit。
您的消费者不应该在使用此包的容器中包含任何容器代码,他们应该只添加 DbContext 作为构造函数依赖项并让 Autofac 完成工作。