'EF Core 2.1 - No database provider has been configured for this DbContext
I have ASP.Net Core 2.1 with EF Core 2.1. This is how my DbContext class looks like
app.DAL.EF -> Layer
using app.domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
namespace app.EF
{
public class MyAppContext : DbContext
{
public MyAppContext(DbContextOptions<MyAppContext> options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new CustomerConfiguration());
modelBuilder.HasDefaultSchema("app");
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
}
public DbSet<Customer> Customers { get; set; }
}
public class MyAppContextConfiguration : IDesignTimeDbContextFactory<MyAppContext>
{
public MyAppContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT ") ?? "Production" }.json", optional: true)
.Build();
var optionsBuilder = new DbContextOptionsBuilder<MyAppContext>();
//optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
var dbConString = configuration.GetConnectionString("ITMDbConnection");
optionsBuilder.UseSqlServer(dbConString);
return new MyAppContext(optionsBuilder.Options);
}
}
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
public void Configure(EntityTypeBuilder<Customer> builder)
{
builder.HasKey(x => x.Id);
}
}}
app.DI -> Layer
public static class Factory
{
public static void Initialize(ref IServiceCollection services)
{
//services.AddTransient<MyAppContext>();
services.AddDbContext<MyAppContext>(options =>
{
});
//services.AddTransient<MyAppContextConfiguration>();
services.AddTransient<ICustomerRepository, CustomerRepository>();
}
}
app.API -> Layer
namespace app.api
{
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)
{
Factory.Initialize(ref services);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}}
When running Add-Migration DbInit
from Package Manager Console, throwing the below error
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.
Thanks!
Solution 1:[1]
it is easactly what it says - there is no database provider attached.
Look at all your code. Where do you specify the database provider? Something like UseSqlServer (in OnConfiguring of the DbContext), depending on what database provider you want to use.
Solution 2:[2]
Inside ConfigureServices
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
In appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "SQL connection string"
}
}
Solution 3:[3]
The error is clear - the provider and connection are never configured. All this code could be replaced with this context :
public class MyAppContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public MyAppContext(){}
public MyAppContext(DbContextOptions<MyAppContext> options)
:base(options)
{}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//The base method is empty
modelBuilder.HasDefaultSchema("app");
}
}
And a call to AddDbContext
inside ConfigureServices
:
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.AddDbContext<MyAppContext>(options =>
{
var dbConString = Configuration.GetConnectionString("ITMDbConnection");
options.UseSqlServer(dbConString);
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
....
}
Most applications have more than one DbContext though. One option would be to add another method to Startup.cs
to register them. For more complex applications, eg applications composed of different domains/modules/subsystems/projects, a better idea would be to create extension methods, eg :
public static CustomerDomainExtensions
{
public static IServicesCollection AddCustomerDomain(this IServicesCollection services,IConfiguration configuration)
{
return services.AddCustomerContexts(configuration)
.AddRepositories(...)
...;
}
public static AddCustomerContexts(this IServicesCollection services,IConfiguration configuration)
{
var dbConString = Configuration.GetConnectionString("ITMDbConnection");
services.AddDbContext<MyAppContext>(options =>
{
options.UseSqlServer(dbConString);
});
//Add more contexts ...
}
}
In Startup.cs
, this would be called inside ConfigureServices
. This is how all Microsoft.Extensions.*
classes work, by providing Add
and Use
extension methods for use in Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddCustomerDomain(Configuration);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
EDIT
Added a default constructor to the DbContext
Solution 4:[4]
I had the same issue.
You need to add base(options) to your constructor.
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{
}
This will pass trough the options parameter to the base constructor.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | TomTom |
Solution 2 | Panagiotis Kanavos |
Solution 3 | |
Solution 4 | Jan Coppens |