My application is layered like so
API -appsettings.json
DAL -configs -appsettings -contexts -mydbcontext
I am simply trying to pass my connection stirng in app settings to my dbcontext through projects and run migrations.
When I hit dotnet ef migrations add initial
I get the error
PM> dotnet ef migrations add changing
Build started...
Build succeeded.
Unable to create an object of type 'PrattleContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
PM>
My program.cs file (in api project)
using Microsoft.EntityFrameworkCore;
using prattle.Data.Configs;
using prattle.Data.Contexts;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//db
builder.Services.AddDbContext <PrattleContext> (option =>
option.UseNpgsql(builder.Configuration.GetConnectionString("prattleDatabase")));
builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("ConnectionStrings").GetSection("prattleDatabase"));
builder.Services.AddOptions();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
appsettings.json (in api project)
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"prattleDatabase": "Host=localhost; Database=prattle; Username=develop; Password=develop123;"
}
}
configs/appsettings ( in data layer )
namespace prattle.Data.Configs
{
public class AppSettings
{
public string prattleDBConnectionString { get; set; }
}
}
contexts/prattlecontext ( in data layer )
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using prattle.Data.Configs;
using prattle.Model.Models;
namespace prattle.Data.Contexts
{
public class PrattleContext : DbContext
{
private IOptions<AppSettings> _appsettings;
public PrattleContext()
{
}
public PrattleContext(IOptions<AppSettings> appsettings)
{
_appsettings = appsettings;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var dbConnectionInfo = _appsettings.Value.prattleDBConnectionString;
optionsBuilder.UseNpgsql(dbConnectionInfo);
}
public DbSet<User> Users { get; set; }
public DbSet<Message> Messages { get; set; }
}
}
I'm guessing the issue is in my program.cs file, but I can't work out why?
CodePudding user response:
First of all builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("ConnectionStrings").GetSection("prattleDatabase"));
will not work as you expect, prattleDBConnectionString
will be null
. To make it work you need to match name of json property and property of class which represents settings:
public class AppSettings
{
public string prattleDatabase { get; set; }
}
Then to bind it correctly you need to use only ConnectionStrings
section:
builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("ConnectionStrings"));
Also note that the setup via options you are using is not an idiomatic way to manage EF Core context, usually you need only one
And the Startup project selected in the solution explorer (select the API one).
If you still want to use dotnet ef tool you may need to specify next options:
Option | Short | Description |
---|---|---|
--project <PROJECT> |
-p |
Relative path to the project folder of the target project. Default value is the current folder. |
--startup-project <PROJECT> |
-s |
Relative path to the project folder of the startup project. Default value is the current folder. |
With -p
set to the project containing the context and -s
set to the API project with connection string.