7
votes

I been searching around now for a clear cut answer on this issue, including github and still cannot see what I am missing here:

Cannot resolve scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[PureGateway.Data.GatewayContext]' from root provider.

In Startup.cs:

        public void ConfigureServices(IServiceCollection services)
        {
            //other code omitted for brevity

            var connection = Configuration.GetConnectionString("DefaultConnection");
            services.AddDbContext<GatewayContext>(options => options.UseSqlServer(connection));
            services.AddDbContextPool<GatewayContext>(options => options.UseSqlServer(connection));
            services.AddScoped<IGatewayRepository, GatewayRepository>();
        }

Usage:

public sealed class MatchBrokerRouteMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<MatchBrokerRouteMiddleware> _logger;

    public MatchBrokerRouteMiddleware(
        RequestDelegate next,
        ILoggerFactory loggerFactory)
    {
        _next = next;
        _logger = loggerFactory.CreateLogger<MatchBrokerRouteMiddleware>();
    }

    public async Task Invoke(HttpContext context, GatewayContext gatewayContext)
    {
            await _next(context);
    }

I am using netcore 2.2.

3
inject into GatewayContext into MatchBrokerRouteMiddleware - Kunal Mukherjee
this can only be done at the method invoke level - read this on GitHub. - IbrarMumtaz
Anybody know if you can inject any type into MW ctor or Invoke() ? Assuming it has been registered ofc. - IbrarMumtaz

3 Answers

7
votes

you either need to use AddDbContext or AddDbContextPool, not both of them.


DbContextPool needs single public constructor. Check my Example below:

public partial class MyDbContext : DbContext
{
    private readonly IUserResolverService _userResolverService;

    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
        _userResolverService = this.GetService<IUserResolverService>();
    }
}
4
votes

I had this same error but found the issue was to do with service lifetime of the DbContextOptions object. By default it is "Scoped" (ie created for each request), whereas the factory expects it to be singleton.

As per this SO answer, the fix was to explicitly set the options lifetime:

services.AddDbContext<GatewayContext>(options => ApplyOurOptions(options, connectionString),
    contextLifetime: ServiceLifetime.Scoped, 
    optionsLifetime: ServiceLifetime.Singleton);
3
votes

If you really need it then you can, the idea is to register as a last line DB options again, since AddPooledDbContextFactory cleans it up. And do not forget to keep only 1 constructor in your DbContext (only this: public MyDbContext(DbContextOptions options) : base(options)):

DbContextOptionsBuilder MsSQL(DbContextOptionsBuilder builder) =>
                builder.UseSqlServer(settings.ConnectionString, x => x.UseNetTopologySuite());
services
    .AddPooledDbContextFactory<MyDbContext>(options => MsSQL(options))
    .AddDbContext<MyDbContext>(options => MsSQL(options))
    .AddScoped<IMyDbContext>(provider => provider.GetService<MyDbContext>())
    .AddSingleton(factory => MsSQL(new DbContextOptionsBuilder()).Options);