Which version of Duende IdentityServer are you using?
5.0.3
Which version of .NET are you using?
.NET 5
Describe the bug
I'm playing around with trying to figure out how to best augment the default DbContexts to add custom functionality. Was planning on having a migrations specific DbContext that encapsulates the default DbContext configurations and adds new entities for our needs in a third DbContext. I don't know if we will go this route but I did uncover a variation in table naming for the "Keys" table. Since its name is not explicitly configured like all the other entities, our migration context ends up naming it "Key" vs. "Keys" unless I include an explicit DbSet named "Keys" in the migration DbContext.
See: Line #175 in ModelBuilderExtensions.cs
To Reproduce
public sealed class MigrationsDataContext : DbContext {
public MigrationsDataContext(DbContextOptions<MigrationsDataContext> options, ConfigurationStoreOptions configurationStoreOptions, OperationalStoreOptions operationalStoreOptions)
: base(options) {
this.ConfigurationStoreOptions = configurationStoreOptions ?? throw new ArgumentNullException(nameof(configurationStoreOptions));
this.OperationalStoreOptions = operationalStoreOptions ?? throw new ArgumentNullException(nameof(operationalStoreOptions));
}
private ConfigurationStoreOptions ConfigurationStoreOptions { get; }
private OperationalStoreOptions OperationalStoreOptions { get; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.ConfigureClientContext(this.ConfigurationStoreOptions);
modelBuilder.ConfigureResourcesContext(this.ConfigurationStoreOptions);
modelBuilder.ConfigurePersistedGrantContext(this.OperationalStoreOptions);
base.OnModelCreating(modelBuilder);
}
}
Expected behavior
I expect the migration to generate a table named "Keys" instead "Key".
Log output/exception with stacktrace
Unhandled exception: Invalid object name 'Keys'.
Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid object name 'Keys'.
at Microsoft.Data.SqlClient.SqlCommand.<>c.b__169_0(Task1 result) at System.Threading.Tasks.ContinuationResultTaskFromResultTask
2.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__277_0(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func
4 operation, Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable
1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1 source, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable
1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToArrayAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Duende.IdentityServer.EntityFramework.Stores.SigningKeyStore.LoadKeysAsync() in //src/EntityFramework.Storage/Stores/SigningKeyStore.cs:line 54
at Duende.IdentityServer.Services.KeyManagement.KeyManager.GetKeysFromStoreAsync(Boolean cache) in //src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs:line 422
at Duende.IdentityServer.Services.KeyManagement.KeyManager.GetAllKeysInternalAsync() in //src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs:line 106
at Duende.IdentityServer.Services.KeyManagement.KeyManager.GetAllKeysAsync() in //src/IdentityServer/Services/Default/KeyManagement/KeyManager.cs:line 93
at Duende.IdentityServer.Services.KeyManagement.AutomaticKeyManagerKeyStore.GetValidationKeysAsync() in //src/IdentityServer/Services/Default/KeyManagement/AutomaticKeyManagerKeyStore.cs:line 105
at Duende.IdentityServer.Services.DefaultKeyMaterialService.GetValidationKeysAsync() in //src/IdentityServer/Services/Default/DefaultKeyMaterialService.cs:line 106
at Duende.IdentityServer.ResponseHandling.DiscoveryResponseGenerator.CreateDiscoveryDocumentAsync(String baseUrl, String issuerUri) in //src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs:line 105
at Duende.IdentityServer.Endpoints.DiscoveryEndpoint.ProcessAsync(HttpContext context) in //src/IdentityServer/Endpoints/DiscoveryEndpoint.cs:line 61
at Duende.IdentityServer.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events, IIssuerNameService issuerNameService, IBackChannelLogoutService backChannelLogoutService) in /_/src/IdentityServer/Hosting/IdentityServerMiddleware.cs:line 84
Additional context
I realize that this is probably not the best way to proceed but it did uncover an inconsistency in the DbContext configuration as it relates to the "Keys" table.