I have created 2 DbContexts for a new ASP.Net Core app.
They are both derived from the same ApplicationDbContext base class, with the only difference being the OnConfiguring override, where UseMySql is used instead of UseSqlite, following what is suggested in this post about multiple providers.
SqliteDbContext.cs has this:
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
#if DEBUG_EF
options.UseSqlite("DataSource=");
#endif
}
MySqlDbContext.cs has this:
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
#if DEBUG_EF
options.UseMySql("Server=");
#endif
}
The following command was run:
dotnet ef migrations add InitialCreate --context MySqlDbContext --output-dir Migrations/MySql --configuration DebugEf
Error returned is:
Unable to create an object of type ‘MySqlDbContext’. For the different
patterns supported at design time, see
https://go.microsoft.com/fwlink/?linkid=851728
However, the following command, which uses the context for Sqlite, is successful.
dotnet ef migrations add InitialCreate --context SqliteDbContext --output-dir Migrations/Sqlite --configuration DebugEf
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This is because in your ConfigureServices method, you’re explicitly configuring a SqliteDbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SqliteDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
...
}
This creates migrations successfully if you change your code to AddDbContext<MySqlDbContext>, but then it would break the Sqlite build.
If you continue reading the article you linked, they describe how to fix this problem:
In your application, you should continue to use
MyDb. However, for
EF to determine which migration to use, you have to call
services.GetService<T>where T is one of the subclasses (instead of
MyDb).Therefore, in
Startup.ConfigureServices, register the subclasses:// Configure database switch (config.DbProvider.ToLower()) { case "sqlite": { services.AddDbContext<MyDb>(options => { options.UseSqlite(config.DbConnString); }); services.AddDbContext<SqliteMyDb>(options => { options.UseSqlite(config.DbConnString); }); } break; case "postgres": { services.AddDbContext<MyDb>(options => options.UseNpgsql(config.DbConnString)); services.AddDbContext<NpgsqlMyDb>(options => options.UseNpgsql(config.DbConnString)); } break; default: { throw new Exception($"DbProvider not recognized: {config.DbProvider}"); } }Then, in Startup.Configure, do the migrations:
void ProcessDb<T>() where T : MyDb { using var db = services.GetService<T>(); db.Database.Migrate(); // ... perform other startup tasks with db } switch (config.DbProvider.ToLower()) { case "sqlite": { ProcessDb<SqliteMyDb>(); break; } case "postgres": { ProcessDb<NpgsqlMyDb>(); break; } default: { throw new Exception(); } }In summary, for each extra provider, add one subclass, a two-line case
in ConfigureServices, and a case in Configure.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0