Pomelo.entityframeworkcore.mysql: 5.0-alpha.2 incompatibility issue with AspNetCore 5.0 WASM templates using IdentityServer

Created on 13 Nov 2020  路  2Comments  路  Source: PomeloFoundation/Pomelo.EntityFrameworkCore.MySql

Steps to reproduce

Create a new .NET Blazor WebAssembly app that is ASP.NET Core hosted with custom user accounts enabled. Then install the alpha2 preview package of Pomelo.EntityFrameworkCore.MySql and replace

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));

with

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseMySql(ServerVersion.AutoDetect(Configuration.GetConnectionString("DefaultConnection"))));

The issue

When creating a migration, updating the database or running the application, you will receive an InvalidOperationException saying that A relational store has been configured without specifying either the DbConnection or connection string to use..

Looking at the stacktrace, it seems it has to do with IdentityServer or Microsoft.AspNetCore.ApiAuthorization.IdentityServer being incompatible with the newest version of this library.

I am opening this issue here rather than on the IdentityServer or Microsoft's library's GitHub because I cannot replicate the issue with EFCore SqlServer, the error only appears once the DbProvider is switched to Pomelo MySql.

System.InvalidOperationException: A relational store has been configured without specifying either the DbConnection or connection string to use.
   at Pomelo.EntityFrameworkCore.MySql.Internal.MySqlOptions.GetConnectionSettings(MySqlOptionsExtension relationalOptions)
   at Pomelo.EntityFrameworkCore.MySql.Internal.MySqlOptions.Initialize(IDbContextOptions options)
   at Microsoft.EntityFrameworkCore.Internal.SingletonOptionsInitializer.EnsureInitialized(IServiceProvider serviceProvider, IDbContextOptions options)
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.<>c__DisplayClass4_0.<GetOrAdd>g__BuildServiceProvider|3()
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.<>c__DisplayClass4_0.<GetOrAdd>b__2(Int64 k)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd(IDbContextOptions options, Boolean providerRequired)
   at Microsoft.EntityFrameworkCore.DbContext..ctor(DbContextOptions options)
   at Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserContext`5..ctor(DbContextOptions options)
   at Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext`8..ctor(DbContextOptions options)
   at Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext`3..ctor(DbContextOptions options)
   at Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext`1..ctor(DbContextOptions options)
   at Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ApiAuthorizationDbContext`1..ctor(DbContextOptions options, IOptions`1 operationalStoreOptions)
   at BlazorApp4.Server.Data.ApplicationDbContext..ctor(DbContextOptions options, IOptions`1 operationalStoreOptions) in C:\Users\local\source\repos\BlazorApp4\BlazorApp4\Server\Data\ApplicationDbContext.cs:line 16
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   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.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_3.<FindContextTypes>b__11()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
A relational store has been configured without specifying either the DbConnection or connection string to use.

Further technical details

MySQL version: 8.0.20
Operating system: Windows 10 Pro 10.0.19041
Pomelo.EntityFrameworkCore.MySql version: 5.0.0-alpha.2
Microsoft.AspNetCore.App version: .NET 5.0

closed-question type-question

Most helpful comment

By the looks of it (not tested yet), you forgot to set the connection string.

You replaced the UseSqlServer(string connectionString) call, that sets the connection string that should be used, with UseMySql(ServerVersion serverVersion), that does not set the connection string, but only the server version (which you auto detect using a connection string).

What you want to do is the following:

```c#
var connectionString = Configuration.GetConnectionString("DefaultConnection");

services.AddDbContext(options =>
options.UseMySql(
connectionString, // <-- set the connection string to use by Pomelo
ServerVersion.AutoDetect(connectionString))); // <-- auto detect the server version using a connection string
```

EF Core 5.0 added UseSqlServer() etc. methods, that don't force you to setup a connection string or connection at the time of the call. That is why we now also have a UseMySql() method without a connection string or connection parameter. If you would use this new method though, you would still need to setup the connection string or connection before EF Core tries to use a connection for the first time, or you will get the exception that you posted (see RelationalDatabaseFacadeExtensions.SetConnectionString()).

All 2 comments

By the looks of it (not tested yet), you forgot to set the connection string.

You replaced the UseSqlServer(string connectionString) call, that sets the connection string that should be used, with UseMySql(ServerVersion serverVersion), that does not set the connection string, but only the server version (which you auto detect using a connection string).

What you want to do is the following:

```c#
var connectionString = Configuration.GetConnectionString("DefaultConnection");

services.AddDbContext(options =>
options.UseMySql(
connectionString, // <-- set the connection string to use by Pomelo
ServerVersion.AutoDetect(connectionString))); // <-- auto detect the server version using a connection string
```

EF Core 5.0 added UseSqlServer() etc. methods, that don't force you to setup a connection string or connection at the time of the call. That is why we now also have a UseMySql() method without a connection string or connection parameter. If you would use this new method though, you would still need to setup the connection string or connection before EF Core tries to use a connection for the first time, or you will get the exception that you posted (see RelationalDatabaseFacadeExtensions.SetConnectionString()).

Awesome, can't thank you enough for the quick reply, that was the issue. Guess I overlooked that in the whole upgrading chaos to 5.0, had a look at the breaking changes of EFCore 5, but apparently this behaviour change wasn't considered one, so I probably missed it because of that.

Was this page helpful?
0 / 5 - 0 ratings