Search code examples
c#entity-framework-coreentity-framework-migrations

"No database provider has been configured for this DbContext" Entity Framework Core


I'm using standalone Entity Framework Core with Discord.NET. I have created a DbContext and added it as a service inside my program entry point.

For some reason I am getting this error whenever I try and create a migration and I just cannot figure out what is causing this.

dotnet ef migrations add Initial 

The error:

Unable to create a 'DbContext' of type ''. The 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.' was thrown while attempting to create an instance.

For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

/DataContext.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace Boolean;

public class DataContext : DbContext
{
    public DataContext() { }
    public DataContext(DbContextOptions<DbContext> options) : base(options) {}
    
    public DbSet<Server> Servers { get; set; }
}

[Table("servers")]
public class Server
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [Column("id")] public UInt64 Id { get; set; }
    [Column("snowflake")] public UInt64 Snowflake { get; set; }
}

/Program.cs

using System.Reflection;
using Discord;
using Discord.Interactions;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Boolean;

class Program
{
    private static Config _config;

    static IServiceProvider ConfigureServices()
    {
        return new ServiceCollection()
            .AddSingleton(_config)
            .AddDbContext<DataContext>(options => options.UseNpgsql(_config.GetConnectionString()))
            .BuildServiceProvider();
    }
    
    public static async Task Main()
    {
        _config = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .Build().Get<Config>()
                  ?? throw new Exception("Failed to load appsettings.json. Please refer to the README.md for instructions.");
        
        _serviceProvider = ConfigureServices();
        await Task.Delay(Timeout.Infinite);
    }
}

Removing the public DataContext() { } method overload results in:

Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Microsoft.EntityFrameworkCore.DbContext]'

Thanks in advance.


Solution

  • You only created the DI but in runtime .NET can't use it because of not setting up it correctly, usually, we need to embed DI into runtime so that runtime can use it to instantiate classes using their constructor.

    In a very simple version, this should work for adding migrations:

    class Program
    {
        public static async Task Main()
        {
            var builder = Host.CreateApplicationBuilder();
    
            var configs = builder.Configuration;
    
            builder.Services.AddDbContext<DataContext>(options =>
            {
                options.UseNpgsql(configs.GetConnectionString("connectionName"));
            });
    
            var app = builder.Build();
    
            await app.RunAsync();
        }
    }
    

    The Host is in the Microsoft.Extensions.Hosting namespace so be sure you install the Nuget package.