使用Npgsql更新数据库/移除迁移时出现Couldn't set databaseconfig错误
场景还原
配置基于EntityFrameworkCore和PostgreSQL(Npgsql驱动)的.NET项目,数据库通过Docker容器部署并已用脚本完成初始化(数据库、用户、模式均已正常创建)。执行ef migrations add成功生成迁移文件,但执行update-database或remove-migration时抛出以下错误:
System.ArgumentException: Couldn't set databaseconfig (Parameter 'databaseconfig')
---> System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at Npgsql.NpgsqlConnectionStringBuilder.GeneratedSetter(String keyword, Object value)
at Npgsql.NpgsqlConnectionStringBuilder.set_Item(String keyword, Object value)
--- End of inner exception stack trace ---
at Npgsql.NpgsqlConnectionStringBuilder.set_Item(String keyword, Object value)
at System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(String value)
at Npgsql.NpgsqlConnectionStringBuilder..ctor(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.Internal.Migrator.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)
错误原因
DatabaseConfig类中生成的连接字符串使用了错误的参数名:DatabaseConfig={Name},而Npgsql的连接字符串规范中不存在databaseconfig这个关键字,正确的数据库名称参数应为Database或DatabaseName。
解决方案
修改DatabaseConfig类的ConnectionString属性,将错误的参数名替换为Database:
public class DatabaseConfig { public string Host { get; set; } public int Port { get; set; } public string Schema { get; set; } public string Name { get; set; } public string User { get; set; } public string Password { get; set; } public string ConnectionString { get { return $"Server={Host},{Port};Database={Name};User Id={User};Password={Password};SearchPath={Schema}"; } } }
额外优化建议
- 上下文类
MyContext中的OnConfiguring方法属于重复配置,因为已经在Startup.ConfigureDatabase中通过AddDbContext指定了连接字符串和命名约定,可以移除该方法,避免冲突:
public class MyContext : DbContext { private readonly DatabaseConfig databaseConfig; public DbSet<Brand> Brands { get; set; } public MyContext(DbContextOptions<MyContext> options, DatabaseConfig databaseConfig) : base(options) => this.databaseConfig = databaseConfig; protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema(databaseConfig.Schema); } }
- 连接字符串中添加
SearchPath={Schema},明确指定默认搜索的数据库模式,与上下文的HasDefaultSchema配置保持一致。
内容的提问来源于stack exchange,提问作者chenny

