7

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.

IbrarMumtaz
  • 3,846
  • 5
  • 39
  • 58

3 Answers3

7

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>();
    }
}
Derviş Kayımbaşıoğlu
  • 24,022
  • 2
  • 42
  • 59
  • Thank you - i was following a blog post where i saw that. :S Am now dealing with: System.InvalidOperationException: 'The DbContext of type 'GatewayContext' cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions.' – IbrarMumtaz Jan 09 '19 at 13:46
  • Found it - auto gen'ed default ctor. – IbrarMumtaz Jan 09 '19 at 13:55
3

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);
2

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);
Mark Foreman
  • 1,250
  • 11
  • 11