efcore.pg
efcore.pg copied to clipboard
7.0.11 gives `__EFMigrationsHistory already exists` on `dbContext.Database.Migrate();`
After updating from 7.0.4 to 7.0.11 I get the error: Npgsql.PostgresException: '42P07: relation "__EFMigrationsHistory" already exists' on running dbContext.Database.Migrate(); from the program.cs in an winforms (core 7.0.11) application.
My connect string looks like this: "Host=localhost;Database=dev_copy;Username=postgres;Password=postgres; SearchPath = schema_prod"
After downgrading Npgsql back to 7.0.4 it works again as expected.
Given the only change in 7.0.11 is #2787 and this is related to schema I suspect migrations on a different schema now always default to public and the default schema is not used in this development db.
@roji Sorry to tag you, but have you seen this issue?
Yes, but I'm currently busy with other urgent matters... I'll try to take a look at this as soon as I can.
As a temporary workaround you can explicitly set the MigrationHistoryTable schema. We do something like this:
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString);
var searchPaths = connectionStringBuilder.SearchPath?.Split(',');
options.UseNpgsql(connectionString, o =>
{
configure(o);
if (searchPaths is {Length: > 0})
{
var mainSchema = searchPaths[0];
o.MigrationsHistoryTable(HistoryRepository.DefaultTableName, mainSchema);
}
})
It's not very elegant, but it works.
Thanks @zlepper this works!
Thanks @zlepper this helped me also in Npgsql Version 6.0.10 (Npgsql.EntityFrameworkCore.PostgreSQL Version 6.0.22).
I am seeing the same issue with version 8.0.0
Here are the steps to reproduce this issue.
- Connect to the "postgres" database and execute this command to create a user.
CREATE ROLE mydbusr WITH
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT
NOREPLICATION
CONNECTION LIMIT -1
PASSWORD 'password';
- Then execute this command to create a database.
CREATE DATABASE "MyDb"
WITH
OWNER = postgres
ENCODING = 'UTF8'
CONNECTION LIMIT = -1
IS_TEMPLATE = False;
- Connect to the "MyDb" database and execute this command to create a schema.
CREATE SCHEMA mydbusr AUTHORIZATION mydbusr;
- Create a class library project and add the EF Core packages.
dotnet new classlib -o EfCoreBug
cd EfCoreBug
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.0
dotnet add package Microsoft.EntityFrameworkCore.Design --version 8.0.0
- Copy/Paste this code into the class library project.
using Microsoft.EntityFrameworkCore;
namespace EfCoreBug;
public class MyContext : DbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseNpgsql("Host=localhost;Username=mydbusr;Password=password;Database=MyDb");
}
public class MyEntity
{
public int Id { get; set; }
}
- Create the Entity Framework migration and update the database.
dotnet ef migrations add InitialCreate
dotnet ef database update
- Change the model.
using Microsoft.EntityFrameworkCore;
namespace EfCoreBug;
public class MyContext : DbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseNpgsql("Host=localhost;Username=mydbusr;Password=password;Database=MyDb");
}
public class MyEntity
{
public int Id { get; set; }
+ public string? NewColumn { get; set; }
}
- Create a new migration.
dotnet ef migrations add AddNewColumn
- Try to apply the new migration.
dotnet ef database update
You should get the following error output.
Failed executing DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);
Npgsql.PostgresException (0x80004005): 42P07: relation "__EFMigrationsHistory" already exists
at Npgsql.Internal.NpgsqlConnector.ReadMessageLong(Boolean async, DataRowLoadingMode dataRowLoadingMode, Boolean readingNotifications, Boolean isReadingPrependedMessage)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming, CancellationToken cancellationToken)
at Npgsql.NpgsqlDataReader.NextResult()
at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteReader(Boolean async, CommandBehavior behavior, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteNonQuery(Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlCommand.ExecuteNonQuery()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
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)
Exception data:
Severity: ERROR
SqlState: 42P07
MessageText: relation "__EFMigrationsHistory" already exists
File: heap.c
Line: 1146
Routine: heap_create_with_catalog
42P07: relation "__EFMigrationsHistory" already exists
As a temporary workaround you can explicitly set the MigrationHistoryTable schema. We do something like this:
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString); var searchPaths = connectionStringBuilder.SearchPath?.Split(','); options.UseNpgsql(connectionString, o => { configure(o); if (searchPaths is {Length: > 0}) { var mainSchema = searchPaths[0]; o.MigrationsHistoryTable(HistoryRepository.DefaultTableName, mainSchema); } })It's not very elegant, but it works.
Thanks, just suffered this issue and added this code snippet to get around the issue. Only affects my databases where public isn't the main schema.
+1
+1
+1
+1
Everyone, please don't post +1 comments, upvote (👍) the top post instead.
configure(o);
Thanks ! It's works !
But what is function configure ?
Will this be fixed in a future release?