Search code examples
entity-framework-coreidentityserver4entity-framework-migrationsdbcontext

Extend configuration and operational data contexts of Identity Server 4


I want to customize the configuration and operational data contexts of Identity Server 4 .

I let you see the code just for the configuration store, because the code is really similar.

Here my custom store:

internal class MyConfigurationDbContext : ConfigurationDbContext
{
    public MyConfigurationDbContext(DbContextOptions<ConfigurationDbContext> options, ConfigurationStoreOptions storeOptions)
        : base(options, storeOptions)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.HasDefaultSchema("configuration");
    }
}

Here I have the first doubt. I think the signature of the constructor should be

public MyConfigurationDbContext(DbContextOptions<MyConfigurationDbContext> options, ConfigurationStoreOptions storeOptions)

but in this case it cannot convert DbContextOptions<MyConfigurationDbContext> in DbContextOptions<ConfigurationDbContext>

Well, in my sturtup I have this code:

builder.AddConfigurationStore<MyConfigurationDbContext>(options =>
{
    options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
        sql => sql.MigrationsAssembly(MIGRATION_ASSEMBLY));
});

Then, I try to generate first migration:

Add-Migration InitialIdentityServerPersistedGrantDbMigration -Context MyConfigurationDbContext -OutputDir Data/Migrations/IdentityServer/PersistedGrantDb

But in this case, I get this error:

Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext]' while attempting to activate 'My.IdentityServer.DataLayer.Repository.Contexts.MyConfigurationDbContext'.

How can I solve it?

Thank you


Solution

  • As you correctly guessed, you have to use DbContextOptions<MyConfigurationDbContext> type for options argument in your context constructor.

    But in order to be able to call the base constructor, instead of the default non generic ConfigurationDbContext you should inherit your context from the generic ConfigurationDbContext<TContext> using your context type as a generic type argument:

    internal class MyConfigurationDbContext : ConfigurationDbContext<MyConfigurationDbContext>
    {
        public MyConfigurationDbContext(DbContextOptions<MyConfigurationDbContext> options, ConfigurationStoreOptions storeOptions)
            : base(options, storeOptions)
        {
        }
    
        // ...
    }