Skip to content

Commit 8a4cae1

Browse files
authored
fix: move JSON function creation into EF Core migrations to prevent startup failure on restart (#1313)
* fix: use CREATE OR ALTER/REPLACE FUNCTION to prevent startup failure on restart On application restart the hosted service fails with: SqlException: There is already an object named 'json_exists' in the database. The #if RELEASE guard in JsonFunction.cs skips DROP FUNCTION IF EXISTS statements in release builds, so CREATE FUNCTION fails if the functions already exist from a previous run. Replace the DROP + CREATE pattern with idempotent alternatives: - SQL Server: CREATE OR ALTER FUNCTION (supported since SQL Server 2016 SP1) - MySQL: CREATE OR REPLACE FUNCTION PostgreSQL was already using CREATE OR REPLACE FUNCTION correctly. DROP FUNCTION IF EXISTS statements are removed from both SQL files. * Move JSON function creation into EF Core migrations - Replace SqlDialectInitializer startup logic with proper EF Core migrations for all three providers (MySQL, SQL Server, Postgres) - SQL Server: uses CREATE OR ALTER FUNCTION (idempotent, no DROP needed) - MySQL: uses DROP FUNCTION IF EXISTS + CREATE FUNCTION in migration - Remove SqlDialectInitializer registration from production ServiceExtensions - Add migration tests: idempotency and upgrade-from-pre-migration-database * Add Postgres migration tests; fix image tag for arm64 compatibility * Replace DatabaseCreator+SqlDialectInitializer with DatabaseMigrator in test fixtures - Test fixtures now use the same code path as production (MigrateAsync) - DatabaseCreator and SqlDialectInitializer are no longer needed and deleted - Functions are created via the AddJsonFunctions migration, not at every startup * Fix missing Squidex.Infrastructure using in test fixtures * Fix test fixtures: use EnsureCreated+Dialect.InitializeAsync and per-prefix migration history Two bugs fixed in the EF Core test fixtures (PostgresFixture, MySqlFixture, SqlServerFixture): 1. Replace DatabaseMigrator with EnsureCreatedAsync + Dialect.InitializeAsync TestDbContext* are test-only contexts with no EF migration files, so DatabaseMigrator<TestDbContext*>.InitializeAsync called MigrateAsync which was a complete no-op — no tables were ever created and all integration tests failed with 'relation does not exist'. EnsureCreatedAsync builds the schema directly from the EF Core model, which is the correct approach for contexts without migrations. Dialect.InitializeAsync is then called explicitly to create the database-specific JSON functions (json_exists etc.) that EnsureCreated does not set up. 2. Add per-prefix MigrationsHistoryTable for named ContentDbContext registrations DynamicTables.PrepareAsync calls MigrateAsync on the named ContentDbContext (e.g. PostgresContentDbContext) to create per-app/schema dedicated tables such as '__c5_ContentsAll'. The migration (AddInitial) reads TableName.Prefix to build the table name at runtime. All named contexts shared the default '__EFMigrationsHistory' table, so after the first prefix ran AddInitial and recorded it, every subsequent prefix saw the migration as already applied and skipped it — leaving its dedicated tables uncreated and causing 'relation __cN_ContentsAll does not exist' failures in all but the first dedicated-table test. Setting options.MigrationsHistoryTable(\$"{name}MigrationHistory") gives each prefix its own independent migration history, so AddInitial runs once per prefix and creates the correct tables each time. Also add *.lscache to .gitignore (C# language server cache files).
1 parent 65b6184 commit 8a4cae1

18 files changed

Lines changed: 5375 additions & 134 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ launchSettings.json
3535

3636
/frontend/app-config/localhost-key.pem
3737
/frontend/app-config/localhost.pem
38+
39+
# C# language server cache
40+
*.lscache

backend/src/Squidex.Data.EntityFramework/Infrastructure/Migrations/DatabaseCreator.cs

Lines changed: 0 additions & 42 deletions
This file was deleted.

backend/src/Squidex.Data.EntityFramework/Infrastructure/Queries/SqlDialectInitializer.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)