Efcore: Improve exception message: The DbContext of type cannot be pooled because it does not have a single public constructor

Created on 24 Oct 2019  Â·  7Comments  Â·  Source: dotnet/efcore

return exception

``` C#
services.AddDbContextPool();

public DataAccessDbContext(DbContextOptions options)
: base(options)
{

    }

    public DataAccessDbContext(DbContextOptions<DataAccessDbContext> options, IDateTimeService dateTimeService, ICurrentUserService currentUserService)
    : base(options)
    {
        _dateTimeService = dateTimeService;
        _currentUserService = currentUserService;
    }

Got Exceptions? Include both the message and the stack trace

System.InvalidOperationException: The DbContext of type 'DataAccessDbContext' cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions.
at Microsoft.EntityFrameworkCore.Internal.DbContextPool1..ctor(DbContextOptions options) at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__52.b__5_1(IServiceProvider sp)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitSingleton(SingletonCallSite singletonCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetServiceT
at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__52.<AddDbContextPool>b__5_2(IServiceProvider sp) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at OpenIddict.EntityFrameworkCore.OpenIddictApplicationStoreResolver.Get[TApplication]() at OpenIddict.Core.OpenIddictApplicationCache1..ctor(IOptionsMonitor`1 options, IOpenIddictApplicationStoreResolver resolver)
```

Further technical details

EF Core version: 2.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: 2.2
Operating system: Win10
IDE: Visual Studio 2019 16.3

closed-fixed customer-reported type-bug

Most helpful comment

We could improve the exception message:
The DbContext of type 'DataAccessDbContext' cannot be pooled because it does not have a public constructor accepting a single parameter of type DbContextOptions or has more than one constructor

All 7 comments

We could improve the exception message:
The DbContext of type 'DataAccessDbContext' cannot be pooled because it does not have a public constructor accepting a single parameter of type DbContextOptions or has more than one constructor

Just came across this error message after generating an EF context from an existing database using “dotnet ef dbcontext scaffold”. Scaffold creates two constructors one with a parameter of type DbContextOptions and another without any parameter.

I wondered why the context must have exactly one constructor with a single parameter of type DbContextOptions. Couldn’t EF/Pooling not just ignore all constructors with a different signature?

The requirement for just having one matching constructor means that one must delete the default constructor after every update/rebuild of the context using scaffold…which is somewhat annoying.

@DaveSenn We will look into allowing the parameterless constructor. It won't be functional in a pooling scenario, but it may be okay to ignore it.

Why is a limitation to use services when using pooling?
For example I need a constructor to use a service so I can use UpdateValuesBeforeSaving to get the current userId in the session. That data is coming from outside. It is a question that I have. There's another way? Thank you.

@ajcvickers That would be great. Ignoring the default constructor would solve our issue. Adding support for DI constructor injection as @mhosman suggests would also be ok... but i don't know how EF would pick the correct constructor? (maybe only one constructor with a parameter of type DbContextOptions allowed?)

@mhosman The DbContext is resolved once from the first service provider scope, and then that instance is re-used from the pool in future requests. This means that dependencies aren't resolved from the request, and would end up being stale. If you need other dependencies injected, then the solution is to not use pooling; it's unlikely that you will see any perf improvement from pooling in a scenario like this anyway.

Was this page helpful?
0 / 5 - 0 ratings