Reputation: 8981
We have the following code to configure the 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));
}
};
}
All of our consumers are autodiscovered through reflection once our application starts up. We have a DbContext
that we want to use in many of our consumers. The problem we face is that the DbContext is disposed due to it being registered as InstancePerLifetimeScope
. More details here:
AspNet Core Autofac disposing my DbContext even if its registered as SingleInstance
Two suggestions came from this post:
DbContext
as InstancePerDependency
LifetimeScope
The first suggestion wont work in our application as we have a UnitOfWork which triggers the SaveChangesAsync
on the DbContext
. The result would be that the Repository
and the UnitOfWork
will get two different instances of the DbContext
and SaveChangesAsync
will not persist our changes as the ChangeTracker
has no changes in the UnitOfWork
implementation, but these changes belongs to the instance in the Repository
.
The second suggestion works perfectly. Within my Consumer
I create a new LifetimeScope
and resolves the components that I need:
public async Task Consume(ConsumeContext<RetailerCreatedEvent> context)
{
using (var scope = _serviceProvider.CreateScope())
{
var unitOfWork = scope.ServiceProvider.GetRequiredService<IUnitOfWork<MyDbContext>>();
}
}
It works, but it doesn't look that good.
Is there a way to start a new LifetimeScope
before the Consumer
triggers? Or should I rewrite my UnitOfWork-pattern to ensure that the same DbContext is being reused in the Repositories
and the UnitOfWork
?
Suggestions are much appreciated
Upvotes: 2
Views: 1478
Reputation: 33278
You need to use the MassTransit.Autofac
package to resolve your consumers, which will use the AutofacScopeProvider (part of the package) to create a lifetime scope and resolve your consumer.
The documentation shows the configuration, including how to automatically discover your consumers via scanning and add them to MassTransit.
Your consumers shouldn't have any container code in them using this package, they should just add DbContext as a constructor dependency and let Autofac do the work.
Upvotes: 3