Home > other >  Entity Framework Core with dependency injection with singletons
Entity Framework Core with dependency injection with singletons

Time:03-30

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:

  1. Either you shorten the lifestyle of your singleton component to either Transient or Scoped
  2. 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>();
            }
        }
    }
    
  • Related