ASP.NET Core Dependency Injection – Cannot consume scoped service
When working with ASP.NET Core and it’s Dependency Injection container, you will likely run into an error that’s similar to this one:
Some services are not able to be constructed (Error while validating the service descriptor ‘ServiceType: AspNetCoreDi.IMyConnectionManager Lifetime: Singleton ImplementationType: AspNetCoreDi.MyConnectionManager’: Cannot consume scoped service ‘AspNetCoreDi.IMyScopedService’ from singleton ‘AspNetCoreDi.IMyConnectionManager’.)
This happens when you have something like this:
So, what’s going on here? Your singleton IMyConnectionManager
would get an instance of IMyScopedService
, and every other time you try to get an instance of IMyConnectionManager
, since it’s singleton it will have the same state, and it will always contain the same instance of IMyScopedService
, meaning that IMyScopedService
effectively becomes a singleton inside of MyConnectionManager
.
Recommended reading: Dependency injection in ASP.NET Core
In ASP.NET Core we have 3 types of service lifetimes:
- Singleton – they’re created first time they’re request, and every time after that the same instance will be reused
- Scoped – they’re created once per the request (connection)
- Transient are created every time you request them from the DI container
You should almost never consume scoped service or transient service from a singleton. You should also avoid consuming transient service from a scoped service.
What is happening when you consume scoped service from a singleton service is known as a captive dependency. It occurs when a service intended to live for a short(er) amount of time gets held by a service that lives for a more extended amount of time. This almost always suggests that you should change something in your design.