diff --git a/BTCPayServer/Data/ApplicationDbContextFactory.cs b/BTCPayServer/Data/ApplicationDbContextFactory.cs index 8e6171d49..1571a34ad 100644 --- a/BTCPayServer/Data/ApplicationDbContextFactory.cs +++ b/BTCPayServer/Data/ApplicationDbContextFactory.cs @@ -6,6 +6,11 @@ using System.Threading.Tasks; using Hangfire; using Hangfire.MemoryStorage; using Hangfire.PostgreSql; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations; +using JetBrains.Annotations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Metadata; namespace BTCPayServer.Data { @@ -31,12 +36,56 @@ namespace BTCPayServer.Data return new ApplicationDbContext(builder.Options); } + class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator + { + public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies) : base(dependencies) + { + } + + protected override void Generate(NpgsqlCreateDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder) + { + builder + .Append("CREATE DATABASE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); + + // POSTGRES gotcha: Indexed Text column (even if PK) are not used if we are not using C locale + builder + .Append(" TEMPLATE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("template0")); + + builder + .Append(" LC_CTYPE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("C")); + + builder + .Append(" LC_COLLATE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("C")); + + builder + .Append(" ENCODING ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("UTF8")); + + if (operation.Tablespace != null) + { + builder + .Append(" TABLESPACE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Tablespace)); + } + + builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); + + EndStatement(builder, suppressTransaction: true); + } + } + public void ConfigureBuilder(DbContextOptionsBuilder builder) { if (_Type == DatabaseType.Sqlite) builder.UseSqlite(_ConnectionString); else if (_Type == DatabaseType.Postgres) - builder.UseNpgsql(_ConnectionString); + builder + .UseNpgsql(_ConnectionString) + .ReplaceService(); } public void ConfigureHangfireBuilder(IGlobalConfiguration builder)