首页 > 解决方案 > 错误:System.InvalidOperationException:没有为此 DbContext 配置数据库提供程序

问题描述

开始

我一直在尝试启动一个小项目,以便我可以学习 EF 并使用 C# 创建 API。我正在关注API 的本教程并遵循EF 设置的本教程。最初,我在创建初始迁移时遇到了问题。这导致我发现有关创建 DbContextFactory 的信息。那行得通,我能够创建并运行我的初始迁移。但是,现在,每当我尝试调用我的 API 路由时,我都会收到此错误:

System.InvalidOperationException:没有为此 DbContext 配置数据库提供程序。可以通过覆盖“DbContext.OnConfiguring”方法或在应用程序服务提供程序上使用“AddDbContext”来配置提供程序。如果使用了“AddDbContext”,那么还要确保您的 DbContext 类型在其构造函数中接受 DbContextOptions 对象并将其传递给 DbContext 的基本构造函数。在 Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider,IDbContextOptions contextOptions,DbContext 上下文)
在 Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() 在 Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() 在 Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_EntityFinderFactory() 在 Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_Finder() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.FindAsync(Object[] keyValues) at Games.Controllers.GameController.Get(Int32 id) in K:\Projects\c#\Games\Games\Controllers\GameController.cs:line 23 at lambda_method5(Closure, Object) at Microsoft .AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper 映射器,ObjectMethodExecutor 执行器,对象控制器,Object[] 参数)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker 调用程序,ValueTask`1 actionResultValueTask)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker 调用程序,Task lastTask,State next,Scope 范围,Object state,Boolean isCompleted)在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker。Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() 的 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) 的 Rethrow(ActionExecutedContextSealed context) --- 堆栈结束从先前位置跟踪 --- 在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker 的 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker .g__Awaited|17_0(ResourceInvoker 调用程序,任务任务,IDisposable 范围)在 Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(端点端点,任务 requestTask,ILogger 记录器)在 Microsoft.AspNetCore.Authorization.AuthorizationMiddleware。Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

在我开始编写代码之前,我的项目已设置好,以便我在同一个解决方案中拥有 API 项目和数据库项目。API 项目是启动项目,依赖于数据库项目。我也在使用 EF Core 5.0 和 .NET 5。

编码

GameDbContext.cs

using Games.Db.Tables;
using Microsoft.EntityFrameworkCore;

namespace Games.Db
{
    public class GameDbContext : DbContext
    {
        public GameDbContext(DbContextOptions<GameDbContext> options) : base(options)
        {

        }

        public DbSet<Game> Game { get; set; }
        public DbSet<Platform> Platform { get; set; }
        public DbSet<Medium> Medium { get; set; }
    }
}

GameDbContextFactory.cs

using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;

namespace Games.Db
{
    public class GameDbContextFactory : IDesignTimeDbContextFactory<GameDbContext>
    {
        public GameDbContext CreateDbContext(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("migrations.json")
                .Build();
            var optionsBuilder = new DbContextOptionsBuilder<GameDbContext>();
            var connectionString = configuration.GetConnectionString("MigrationsHelperConnection");
            optionsBuilder.UseSqlServer(connectionString);

            return new GameDbContext(optionsBuilder.Options);
        }
    }
}

启动.cs

using Games.Db;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace Games
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddDbContext<GameDbContext>();

            services.AddTransient<DbContext, GameDbContext>();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Games", Version = "v1" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Games v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

我尝试了什么

我发现了这个问题,并将其添加OnConfiguring()到我的 GameDbContext 中,并创建了这个:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var directory = Directory.GetCurrentDirectory();
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("migrations.json")
            .Build();
        var connectionString = configuration.GetConnectionString("MigrationsHelperConnection");
        optionsBuilder.UseSqlServer(connectionString);
    }

但是,此时我得到的错误是它找不到migrations.json. 这是因为它正在查找我的 API 项目的目录,并且该文件位于我的数据库项目中。

问题

我显然在这一切中遗漏了一些非常微妙的东西。可能是将近凌晨 2 点,咖啡在几个小时前就用完了。但我完全被难住了。我会错过什么?

编辑

这是解决方案布局的图片:

在此处输入图像描述

标签: c#entity-frameworkasp.net-core

解决方案


在 Alexander 的一些提示和指导下,我更新了我的函数以更改Directory

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
        var configuration = new ConfigurationBuilder()
            .SetBasePath(directory)
            .AddJsonFile("migrations.json")
            .Build();
        var connectionString = configuration.GetConnectionString("MigrationsHelperConnection");
        optionsBuilder.UseSqlServer(connectionString);
    }

推荐阅读