I have a new ASP.NET Core Web API project that I'm trying to get set up with Entity Framework Core.
I did my initial migrations and it successfully created a migration class in the Migrations
folder.
I tried to then update the database:
dotnet ef database update
and it fails with:
dotnet ef database update
Build started...
Build succeeded.
System.ArgumentException: Host can't be null
at Npgsql.NpgsqlConnectionStringBuilder.PostProcessAndValidate()
at Npgsql.NpgsqlConnection.SetupDataSource()
at Npgsql.NpgsqlConnection.set_ConnectionString(String value)
at Npgsql.NpgsqlConnection..ctor(String connectionString)
at Npgsql.NpgsqlConnection.CloneWith(String connectionString)
at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlRelationalConnection.CloneWith(String connectionString)
at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlDatabaseCreator.Exists(Boolean async, CancellationToken cancellationToken)
at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlDatabaseCreator.Exists()
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.GetAppliedMigrations()
at Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Internal.NpgsqlMigrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)Host can't be null
I have found a few posts from years ago with this issue but none of them had a solution.
Program.cs
:
using Microsoft.EntityFrameworkCore;
using ShopBack.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddScoped<ProductsService>()
.AddControllers(options => options.SuppressAsyncSuffixInActionNames = false);
builder.Services.AddDbContext<LibraryContext>(options =>
{
options.UseNpgsql(builder.Configuration.GetConnectionString("YourConnectionName"));
});
var app = builder.Build();
// configure request pipeline
app.MapControllers();
app.UseCors (x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.Run();
appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"YourConnectionName": "Host=127.0.0.1; Port=5432; User Id=postgres; Password=postgres; Database=shopback"
}
}
appsettings.Development.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"YourConnectionName": "Host=127.0.0.1; Port=5432; User Id=postgres; Password=postgres; Database=shopback"
}
}
.csproj
:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Npgsql" Version="8.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
As per Michal's comment, I added a --connection parameter with my connection information:
dotnet ef database update --connection "Host=127.0.0.1; Port=5432; User Id=postgres; Password=postgres; Database=shopback"
And the database update command worked and my tables have been created.
I did find this updates page talking about the new --connection
parameter:
But it says the new --connection
is now available in EF Core 5.0 not that the --connection
is the only way to have Entity Framework Core get your connection.
Why wouldn't it pull this from my project's appsettings.json
file?
UPDATE I found the issue. With Entity you create a context class that inherits from DbContext and this is where you define what your tables will look like. My class I use for this is called "LibraryContext" and in my "OnConfiguring" method when I am referencing my connection string I referenced it incorrectly because I was working from examples I found online. See the below code where the incorrect configuration is commented out right above the correct configuration for the connection string.
using Microsoft.EntityFrameworkCore;
public class LibraryContext : DbContext
{
public LibraryContext(DbContextOptions<LibraryContext> options) : base(options){}
public DbSet<Item> Items { get; set; }
public DbSet<Category> Categories { get ; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
// optionsBuilder.UseNpgsql(configuration.GetConnectionString("Database:ConnectionStrings:YourConnectionName"));
optionsBuilder.UseNpgsql(configuration.GetConnectionString("YourConnectionName"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//configure the Item table
modelBuilder.Entity<Item>().ToTable("Item");
modelBuilder.Entity<Item>()
.HasKey(b => b.Id);
modelBuilder.Entity<Item>()
.Property(i => i.Name)
.HasMaxLength(100)
.IsRequired();
modelBuilder.Entity<Item>()
.HasOne(b => b.Category)
.WithMany(c => c.Items)
.HasForeignKey(b => b.CategoryId)
.IsRequired();
//configure the category table
modelBuilder.Entity<Category>().ToTable("Category");
modelBuilder.Entity<Category>()
.HasKey(c => c.Id);
modelBuilder.Entity<Category>()
.Property(c => c.Name)
.HasMaxLength(100)
.IsRequired();
}
}
and once again here is my appsettings.json file. The incorrect reference above would expect the json file to be formatted a bit differently.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"YourConnectionName": "Host=127.0.0.1; Port=5432; User Id=postgres; Password=postgres; Database=shopback"
}
}