EF Core mapping sweep: schema parity with EF Core migrations (tables + indexes) - #361
Merged
Conversation
Adds a dual-schema comparison harness that verifies the tables and indexes Weasel generates for a DbContext are identical to what EF Core's own migration system creates (catalog-level snapshot diff on PostgreSQL and SQL Server, plus zero-delta and idempotency assertions), and fixes every divergence it exposed: - PostgreSQL identifier casing: new ITable.PreserveIdentifierCase seam, quoted PK/FK/index DDL, and case-insensitive delta matching so EF's quoted PascalCase schemas round-trip (fixes the previously failing can_apply_migration_with_fk_dependencies) - Index mapping: new ITableIndex + ITable.AddIndex across all five providers; the mapper now maps HasIndex (unique/composite/named/ filtered/INCLUDE), EF's conventional FK indexes, and alternate keys — previously Weasel emitted DROP INDEX for all of them - Literal HasDefaultValue defaults rendered via EF's own type mapping - Client* delete behaviors no longer emit ON DELETE clauses; SQL Server normalizes Restrict as NO ACTION - Identity mapping via ITableColumn.IsAutoNumber (PostgreSQL now emits GENERATED BY DEFAULT AS IDENTITY) with TPT/default/type suppressions - SQL Server FetchExisting honors is_included_column; rowversion synonym; FK catalog parsing strips identifier quoting - TPH nullability via IsColumnNullable, table-split owned entity columns, owned-with-own-table inclusion, row-internal FK skip - New ci-build-efcore.yml (the EF test project ran in no CI workflow); end-to-end tests no longer EnsureDeleted the shared databases; TFM/schema race fixes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… SQL Server On a fresh SQL Server (CI service container) several test classes raced to CREATE DATABASE weasel_testing: one lost with "database already exists" and others hit "cannot open database" logins against the half-created database. Adds a shared SqlServerDatabaseBootstrap that swallows the creation race and retries the login until the database is reachable, and serializes all SQL Server EF test classes into one xunit collection (Azure SQL Edge also deadlocks on concurrent DDL). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jeremydmiller
added a commit
that referenced
this pull request
Jul 18, 2026
…d columns, index methods, drift detection, Oracle/MySql parity (#372) Follow-ups to the EF Core schema-parity sweep (#361): - Sequences: SequenceBase.IncrementBy (HiLo block size), Migrator.CreateSequence seam (PG/SS/Oracle), GetSchemaObjectsForMigration maps model sequences (UseHiLo/UseSequence/HasSequence) ahead of tables; CreateMigrationAsync uses it - Check constraints: TableCheckConstraint in Weasel.Core, ITable.AddCheckConstraint, CREATE emission + catalog reads + conservative delta comparison on PG and SS (only declared checks compared; unknown constraints never dropped) - Computed columns: ITableColumn.ComputedExpression/ComputedColumnIsStored with emission on PG (STORED), SS (AS ... PERSISTED), MySQL, SQLite (mapped onto its existing generated-column model); Oracle throws rather than emitting wrong DDL - Index methods: ITableIndex.Method maps Npgsql HasMethod("gin") automatically - Opt-in column drift detection: ITable.DetectColumnDrift compares canonicalized defaults + nullability of matching columns and emits ALTER corrections on PG/SS; off by default (datetime literal canonicalization is not stable enough to be safe) - Oracle casing parity: preserve-case columns/PK/FK are quoted (folded convention unchanged), covered by DB-free DDL tests - MySQL: EF CI service added, EnsureDeleted hazard removed from its e2e tests - SQL Server FetchExisting reads column defaults/nullability; ItemDelta matching case-insensitive; EF docs updated (casing, sequences, drift, owned types) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
A comprehensive sweep of
Weasel.EntityFrameworkCore's DbContext → Weasel table mapping. It adds a dual-schema comparison harness that, for a matrix of EF Core mapping permutations, verifies at the database-catalog level that the schema Weasel creates is identical to what EF Core's own migration system creates — and that Weasel's delta detection reports zero changes against an EF-created schema (and against its own, for idempotency). Everything the harness exposed is fixed here.See
EFCORE_IMPROVEMENTS.md(repo root) for the full write-up.Bugs found & fixed (all pre-existing on master)
can_apply_migration_with_fk_dependencieswas failing on master because of this. New opt-inITable.PreserveIdentifierCaseseam + quoted PK/FK/index DDL + case-insensitive delta matching. All-lowercase callers (Marten) emit byte-identical DDL as before.IX_*indexes for every FK by convention; Weasel's delta emittedDROP INDEXfor them. New provider-neutralITableIndex/ITable.AddIndex(all five providers); the mapper mapsHasIndex(unique/composite/named/filtered/INCLUDE), conventional FK indexes, and alternate keys.HasDefaultValueliterals silently dropped — now rendered via EF's ownGenerateSqlLiteral(bool/string/Guid/DateTime/enum incl. conversions).ClientSetNull(EF's default for optional FKs) wrongly producedON DELETE SET NULL; allClient*behaviors now map to no action. SQL Server normalizes Restrict ≡ NO ACTION.ITableColumn.IsAutoNumber+ PostgreSQLGENERATED BY DEFAULT AS IDENTITYemission, with correct suppression for defaults, TPT linking keys, and non-integral types.Plus mapper correctness: TPH nullability via
IsColumnNullable, table-split owned entity columns, owned-with-own-table inclusion (over-fix of #234), row-internal FK skip.Test coverage
19 comparison suites (14 PostgreSQL, 5 SQL Server): defaults, composite keys, indexes (incl. SQL Server's automatic
IS NOT NULLfilter on unique-nullable indexes), alternate keys, many-to-many, self-reference + delete-behavior matrix, TPH, TPT, owned entities, facets, identity strategies, rowversion, check constraints (documented gap). Known gaps are each pinned by a test or tolerated diff category.Infrastructure
ci-build-efcore.yml— the EF Core test project previously ran in no CI workflow at all (how a failing test sat on master unnoticed).EnsureDeletedthe sharedmarten_testing/weasel_testingdatabases (they were killing concurrent tests' connections with 57P01).TestTfmsInParallel=false+ xunit collections for schema-sharing classes and Azure SQL Edge DDL deadlocks.Verification
🤖 Generated with Claude Code