简体   繁体   中英

ERROR: System.InvalidOperationException: No database provider has been configured for this DbContext

THE BEGINNING

I've been trying to get a small project started so I can learn EF and creating APIs using C#. I'm following this tutorial for the API and followed this tutorial for EF setup . Initially, I was running across an issue creating my initial migration. This lead to me finding about creating a DbContextFactory . That worked, and I was able to create and run my initial migration. Now, however, I'm getting this error whenever I try calling my API route:

System.InvalidOperationException: 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. at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_EntityFinderFactory() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet 1.get_Finder() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet 1.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 mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Z5D113F2038 D289F391614C39043629E8Z scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at 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)

Before I get to the code, my project is setup so that I have the API project and the Database project in the same solution. The API project is the start up project, and is dependent on the Database project. I'm also using EF Core 5.0 and .NET 5.

THE CODE

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

Startup.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();
            });
        }
    }
}

WHAT I TRIED

I found this question , and added the OnConfiguring() to my GameDbContext, and created this:

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

However, the error I get at this point is that it can't find the migrations.json . This is because it's looking the directory of my API project, and the file is in my Database project.

THE QUESTION

I'm obviously missing something very subtle in all this. Could be that it's almost 2am and the coffee ran out hours ago. But I'm completely stumped. What could I be missing?

EDIT

Here's a picture of solution layout:

在此处输入图像描述

After some prompting and guiding from Alexander, I updated my function to change the 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);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM