Cannot consume scoped service from singleton IHostedService

Today in this article, we will see how to resolve issue InvalidOperationException: Error while validating the service descriptor ‘ServiceType: <> Lifetime: Singleton ImplementationType: <>’: Cannot consume scoped service ‘<>’ from singleton ‘<>’.

Issue Description

You might get similar for different service type but the below discussed technique will help you those all-similar issues when used with their respective type.

ASP.NET Core using IHostedService gives runtime error,

InvalidOperationException: Error while validating the service descriptor ‘ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: kafka_api_producer_consumer.TheCodeBuzzConsumer’: Cannot consume scoped service ‘SQLDBService.Context.EmployeeContext’ from singleton ‘Microsoft.Extensions.Hosting.IHostedService’.

Cannot consume scoped service

Resolution

The reason being when we add AddHostedService to the application or API the Service Instance gets added as SingleTon instance.

As a good practice, EFCore DBContext should be set as a scoped instance.

In fact, EFCore using AddDBContext lets you add a scoped instance of DBContext to be the default.

It’s Important to consume scope services in scoped instances to avoid data corruption or threading issue.

While scope service instances are created once per request it is often recommended they are resolved using a scoped instance of services that use them. You might need to consider the below aspects also before resolving the issue.

Approach 1- Using ServiceScopeFactory to resolve Cannot consume scoped service error

 class TheCodeBuzzConsumer : BackgroundService
    {
        private readonly ILogger<TheCodeBuzzConsumer> _logger;
        private readonly EmployeeContext _employeeContext;

        public TheCodeBuzzConsumer(ILogger<TheCodeBuzzConsumer> logger, IServiceScopeFactory factory)
        {
            _logger = logger;
            _employeeContext = factory.CreateScope().ServiceProvider.GetRequiredService<EmployeeContext>();
        }

The above code let you create Scoped instance of EmployeeContext and is able to work with the Database easily.

Approach 2- Using IServiceProvider to fix Cannot consume scoped service

We shall DI IServiceProvider using constructor injection as below,

class TheCodeBuzzConsumer : BackgroundService
    {
        private readonly ILogger<TheCodeBuzzConsumer> _logger;
        private readonly EmployeeContext _employeeContext;

        public TheCodeBuzzConsumer(ILogger<TheCodeBuzzConsumer> logger, IServiceProvider serviceProvider)
        {
            _logger = logger;
            _employeeContext = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<EmployeeContext>();
        }

  • By doing the above DBContext will be used with the lifetime configuration set up originally.

  • This will also make sure Singleton instances are not created for the given services.

That’s all! Happy coding!

Does this help you fix your issue?

Do you have any better solutions or suggestions? Please sound off your comments below.

References:



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



12 thoughts on “Resolved- Cannot consume scoped service from singleton IHostedService

Leave a Reply

Your email address will not be published. Required fields are marked *