I am trying to use Dependency Injection with a singleton and DBContext.
In .net framework I can do something like this
public class MySingleton
{
private readonly Func<MyDbContext> _getContext;
public MySingleton(Func<MyDbContext> getContext)
{
_getContext = getContext;
}
}
However, when I do this now I get the following error:
Unable to resolve service for type 'System.Func`1[MyDbContext]'
I did try to add this to the constructor.
public class MySingleton
{
private readonly Func<MyDbContext> _getContext;
public MySingleton(IServiceProvider serviceProvider)
{
_getContext =
() => (MyDbContext)serviceProvider.GetService(typeof(MyDbContext));
}
}
However, serviceProvider
returns the same instance
How can I create a new instance of MyDbContext
every time I use it?
CodePudding user response:
When resolving a singleton with MS.DI, that singleton and all its dependencies are resolved from the root scope/container. This is why you experience the behavior where resolving the MyDbContext
from an injected IServiceProvider
always gives the same instance; that scoped instance is scoped to the container. In other words, that scoped instance implicitly became a singleton.
MS.DI's Closure Composition Model makes it very hard to resolve scopes within singletons (without manually managing scopes through ambient state), because scopes are not available ubiquitously through ambient state, as is done using the Ambient Composition Model.
In practice, there are two options here:
- Either you shorten the lifestyle of your singleton component to either
Transient
orScoped
- You start and manage an
IServiceScope
from within the component's methods and resolve the scoped component from such scope. For instance:public class MySingleton { private readonly IServiceProvider provider; public MySingleton(IServiceProvider provider) { this.provider = provider; } public void SomeMethod() { using (var scope = this.provider.CreateScope()) { scope.ServiceProvider.GetRequiredInstancce<MyDbContext>(); } } }