WPF和EntityFrameworkCore-添加迁移将给出“尚未为此DbContext配置数据库提供程序”

注意 我已经阅读了大量看似相似的SO答案,但是我已经按照他们的建议去做,所以我没有知道WPF是否有区别(它们似乎都与ASP.NET有关)。另外,大多数答案都与运行时错误有关,而不是添加迁移时的错误。

我正在尝试建立一个使用EntityFrameWork Core的.NET Core 3 WPF项目,但是在添加迁移时遇到了问题。我将上下文设置如下...

  public class ApplicationDbContext : DbContext {
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
      : base(options) {
    }

    public ApplicationDbContext() {
    }

    public DbSet<Product> Products { get; set; }
  }

无参数构造函数在那里,因为没有它,我会得到一个异常在尝试添加迁移时无法创建类型为'ApplicationDbContext'的对象

我的App.xaml.cs包含以下内容...

  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));
    }
  }

我意识到其中的某些内容是无关紧要的,但我想我会向全班同学展示,以防万一它揭示了我错过的内容。该代码基于此blog post

但是,当我尝试添加迁移时,出现异常“ 没有为此DbContext配置数据库提供程序。可以通过覆盖DbContext.Onconfiguring方法或在应用程序上使用AddDbContext来配置提供程序。服务提供者。如果使用AddDbContext,则还要确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基本构造函数。

据我所知,我已经配置了数据库提供程序。我在ConfigureServices方法中设置了一个断点,可以看到使用正确的连接字符串调用了services.AddDbContext

有人知道我错过了什么吗?

更新,我尝试连接到现有数据库,并且运行良好,因此看来数据库提供程序已正确配置。只有当我尝试添加迁移时,我才例外。

更新2 似乎迁移工具正在上下文中使用无参数构造函数,这就是为什么它认为尚未配置提供程序的原因。如果我从App.xaml.cs中删除对其进行配置的行,而改写Onconfiguring方法来调用UseSqlServer,则迁移可以正常进行。但是,除了我没有看到其他人这样做的事实(这使我想知道这是否真的是正确的方法)之外,我没有看到如何从配置文件中获取连接字符串。我无法注入IConfiguration参数,因为整个问题是迁移需要无参数的构造函数。

fankaoquan 回答:WPF和EntityFrameworkCore-添加迁移将给出“尚未为此DbContext配置数据库提供程序”

使用 .Net Core 3.1 和 EF Core Version 5 实际上很简单,Entity Framework 将查看静态函数 CreateHostBuilder 的入口点类,在我的情况下是 App 类在 app.xaml.cs 中。

不完全确定 .Net Core 3.1 之前所需的约定。根据我的经验,它与使用 .Net Core 2.1 和 ASP.Net 的 Startup 类有关。

https://docs.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli

我的解决方案:

public partial class App : Application
{
    /// <summary>
    /// Necessary for EF core to be able to find and construct
    /// the DB context.
    /// </summary>
    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        return Host.CreateDefaultBuilder(args)
            // Configure Application services
            .ConfigureServices((context,services) =>
            {
                ConfigureServices(context,services);
            });
    }

    /// <summary>
    /// Not necessary but I prefer having a separate function for
    /// configuring services.
    /// </summary>
    private static void ConfigureServices(HostBuilderContext context,IServiceCollection services)
    {
        ...
    }

    /// <summary>
    /// Hold the built Host for starting and stopping
    /// </summary>
    private readonly IHost AppHost;

    /// <summary>
    /// Constructor
    /// </summary>
    public App()
    {
        // Create Application host
        AppHost = CreateHostBuilder(new string[] { }).Build();
    }

    /// <summary>
    /// App Startup Event Handler
    /// </summary>
    private async void Application_Startup(object sender,StartupEventArgs e)
    {
        // Start the application host
        await AppHost.StartAsync();

        ...
    }

    /// <summary>
    /// App Exit Event Handler
    /// </summary>
    private async void Application_Exit(object sender,ExitEventArgs e)
    {
        // Kill the application host gracefully
        await AppHost.StopAsync(TimeSpan.FromSeconds(5));
        // Dispose of the host at the end of execution
        AppHost.Dispose();
    }
}
,

您需要实现IDesignTimeDbContextFactory。 ASP.NET Core应用程序中有很多隐藏的管道,用于连接应用程序服务提供商,因此可以通过dotnet ef工具找到它,但是WPF中没有这样的管道。此外,ef工具对WPF事件一无所知,因此您的OnStartup方法甚至不会被调用(甚至不会创建该类的实例)来创建DI设置,以便ef工具可以找到您的DBContext

将创建ServiceProvider的代码移到构造函数中,而不是查找并显示主窗口的代码。

实施IDesignTimeDbContextFactory<ApplicationDbContext>。在已实现的CreateDbContext方法return ServiceProvider.GetRequiredService<ApplicationDbContext>()

然后,该工具将创建您的类的实例,该实例将设置DI,并调用该方法以获取(现已配置)数据库上下文,并且该方法应该可以工作。

我还建议您转到基于HostBuilder的配置(该博客文章是在发布Core 3最终版本之前编写的)。您将找到同一帖子here

的更新版本
本文链接:https://www.f2er.com/3158131.html

大家都在问