-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't use DbContext in message consumer #34
Comments
What transport provider do you use @GMillerVarian? |
We are using Redis. We have discovered that creating a scope in the dependency resolver seems to have fixed the issue:
Does this seem like the best solution? |
Whenever SMB requires an instance of a consumer to be created it reaches out to the resolver to obtain it from DI. In the above example the It all depends what you want to achieve:
// Startup.cs:
services.AddScoped<SomeConsumer>();
services.AddTransient<SomeConsumer.ScopedWrapper>();
// SMB builder config
x.Consume<SomeEvent>(
x => x.Topic(...)
.WithConsumer<SomeConsumer.ScopedWrapper>());
// the wrapper:
public class ScopedConsumerDecorator<T> : IConsumer<T>
{
private readonly IServiceProvider serviceProvider;
private readonly Type consumerType;
public ScopedConsumerDecorator(IServiceProvider serviceProvider, Type consumerType)
{
this.serviceProvider = serviceProvider;
this.consumerType = consumerType;
}
public async Task OnHandle(T message, string name)
{
using var scope = serviceProvider.CreateScope();
var targetConsumer = (IConsumer<T>)scope.ServiceProvider.GetRequiredService(consumerType);
await targetConsumer.OnHandle(message, name);
}
}
public class SomeConsumer: IConsumer<SomeEvent>
{
private readonly MyDbContect dbContext; // scoped
public CrmEntityEventConsumerForWorkOrder(MyDbContect dbContext) { this.dbContext = dbContext; }
public async Task OnHandle(SomeEvent message, string name)
{
}
public class ScopedWrapper : ScopedConsumerDecorator<SomeEvent>
{
public ScopedWrapper(IServiceProvider serviceProvider) : base(serviceProvider, typeof(SomeConsumer))
{
}
}
} I am planning to add a feature to SMB, so that handlers could just be scoped in the DI and SMB creates a scope for each message and then it disposes the scope after handling.
Please let me know if the above answers. |
Thanks. In our case, we are only reading from the DB (never writing) so I think a single scope is sufficient. |
Closing. Feel free to reopen of you still have questions. |
I'm following the approach in the WebApi sample for our web application. My message consumer needs a DbContext (or a class which needs a DbContext), which must be scoped to avoid concurrency errors. However, since the IMessageBus is a singleton, created when the application starts, it cannot have a scoped service as a dependency. How can the message consumer use a scoped dependency, such as a DbContext?
The text was updated successfully, but these errors were encountered: