Identity stores with DB Context Factory

Viewed 713

On my ASP.NET Core 5.0 project, I changed

services.AddDbContext<SelfProgressDbContext>(...);

to

services.AddPooledDbContextFactory<SelfProgressDbContext>(...);

and now the application is not starting. A subset of errors I got:

Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.UserManager1[SelfProgress.Domain.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager1[SelfProgress.Domain.User]': Unable to resolve service for type 'SelfProgress.Orm.SelfProgressDbContext' while attempting to activate > 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore9[SelfProgress.Domain.User,Microsoft.AspNetCore.Identity.IdentityRole1[System.Guid],SelfProgress.Orm.SelfProgressDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim`1[System.Guid]]'.

Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SecurityStampValidator1[SelfProgress.Domain.User]': Unable to resolve service for type 'SelfProgress.Orm.SelfProgressDbContext' while attempting to activate 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore9[SelfProgress.Domain.User,Microsoft.AspNetCore.Identity.IdentityRole1[System.Guid],SelfProgress.Orm.SelfProgressDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim1[System.Guid]]'.

Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.Guid]] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.Guid]]': Unable to resolve service for type 'SelfProgress.Orm.SelfProgressDbContext' while attempting to activate 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore5[Microsoft.AspNetCore.Identity.IdentityRole1[System.Guid],SelfProgress.Orm.SelfProgressDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim1[System.Guid]]'.

It looks like the Identity EF store classes can no longer resolve the DB Context because of the new pooled DB context factory registration. Using AddPooledDbContextFactory seems you can't resolve DB context directly anymore. Instead, you should resolve the factory and then create a DB context manually.

My Identity registration:

services
    .AddIdentity<User, IdentityRole<Guid>>(...)
    .AddEntityFrameworkStores<SelfProgressDbContext>()
    .AddDefaultTokenProviders()

Is there a way to make default Identity stores resolve the DB context via its new factory?

1 Answers

In the ConfigureServices, try to use AddScoped() method to register the DBContext and use the provider to get the factory from the services. Then, return the instance to the provider. The code like this:

        services.AddDbContextFactory<ApplicationDbContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            options.EnableSensitiveDataLogging();
        });

        services.AddScoped<ApplicationDbContext>(p => p.GetRequiredService<IDbContextFactory<ApplicationDbContext>>().CreateDbContext());

The ApplicationDbContext.cs:

public class ApplicationDbContext : IdentityDbContext
{
     ...
}
Related