Nader Elshehabi
Nader Elshehabi

Reputation: 139

How to get IdentityServer to work with AddDbContextPool

I'm trying to leverage AddDBContextPool in my ASP Core API project that uses IdentityServer for authentication. The problem is, to use PersistedGrants you need to have the DBContext set up this way:

private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;

public ApplicationDbContext(
   DbContextOptions options,
   IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options)
   {
        _operationalStoreOptions = operationalStoreOptions;
   }
    
protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
}

AddDBContextPool requires only a single constructor that takes only DbContextOptions as a parameter. So I can't inject operationalStoreOptions anymore.

I tried using AddOperationalStore() from the Startup class, but I got the following error:

The entity type 'DeviceFlowCodes' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'.

Any idea what am I missing?

Upvotes: 0

Views: 361

Answers (1)

Nader Elshehabi
Nader Elshehabi

Reputation: 139

I ended up manually implementing the IPersistedGrantDbContext interface in my class. The code is below in case this could help anyone else.

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IPersistedGrantDbContext
    {
        public ApplicationDbContext(DbContextOptions options) : base(options)
        {
            // No tracking needed as all transactions are disconnected
            ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        }

        public DbSet<PersistedGrant> PersistedGrants { get; set; } = null!;
        public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; } = null!;

        public Task<int> SaveChangesAsync()
        {
            return base.SaveChangesAsync();
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            OperationalStoreOptions options = new OperationalStoreOptions
            {
                DeviceFlowCodes = new TableConfiguration("DeviceCodes"),
                PersistedGrants = new TableConfiguration("PersistedGrants")
            };

            base.OnModelCreating(builder);
            builder.ConfigurePersistedGrantContext(options);
            
            // ... Rest of configuration here

        }
    }

Upvotes: 2

Related Questions