Note I have read the large number of SO answers that appear to be similar, but I am already doing what they suggested, so I don't know if there is some difference with WPF (they all seem to relate to ASP.NET). Also, most answers relate to run-time errors, not ones when adding migrations.
I'm trying to set up a .NET Core 3 WPF project that uses EntityFrameWork Core, but am having problems adding a migration. I have set up my context as follows...
public class ApplicationDbContext : DbContext {
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) {
}
public ApplicationDbContext() {
}
public DbSet<Product> Products { get; set; }
}
The parameterless constructor is there, as without it I get an exception Unable to create an object of type 'ApplicationDbContext' when trying to add a migration.
My App.xaml.cs
contains the following...
public partial class App {
public IServiceProvider ServiceProvider { get; private set; }
public IConfiguration Configuration { get; private set; }
protected override void OnStartup(StartupEventArgs e) {
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appSettings.json", optional: false, reloadOnChange: true);
Configuration = builder.Build();
ServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
ServiceProvider = serviceCollection.BuildServiceProvider();
MainWindow mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
}
private void ConfigureServices(IServiceCollection services) {
// Configuration
services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));
// Database
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SqlConnection")));
// Windows
services.AddTransient(typeof(MainWindow));
}
}
I realise that some of this is irrelevant, but thought I'd show the whole class in case it reveals something I missed. The code is based on this blog post.
However, when I try to add a migration, I get an exception "No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext."
As far as I can see, I have configured the database provider. I put a breakpoint in the ConfigureServices
method, and can see that services.AddDbContext
is called with the correct connection string.
Anyone any ideas what I've missed?
UPDATE I tried connecting to an existing database, and it worked absolutely fine, so it looks like the database provider has been configured correctly. It's only when I try to add a migration that I get the exception.
UPDATE 2 It seems that the migration tool is using the parameterless constructor on the context, which is why it thinks the provider hasn't been configured. If I remove the lines that configure it from App.xaml.cs, and instead override the OnConfiguring
method to call UseSqlServer
then the migration works fine. However, apart from the fact that I've not seen anyone else doing this (which makes me wonder if it's really the right way to do it), I don't see how to get the connection string from the config file. I can't inject an IConfiguration
parameter, as the whole issue is that migrations requires a parameterless constructor.