Skip to content

v5.4.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 19:15
· 172 commits to main since this release
19c53bb

5.4.0

Fixes to what 5.x already ships, found while testing the packages against EF Core 11 and planning
the next features: indexes on JSON members that no query could use, and constraint names that only
failed — or quietly vanished — when the migration was applied.

  • Fixed: indexes on members of a ToJson() complex property are written the way Npgsql's queries read the member, so PostgreSQL can use them. It uses an expression index only for a query whose expression matches, and until now every member was extracted as "doc" -> 'A' ->> 'B' text with no cast, which matched only a top-level string. A nested member (#>> '{Address,City}' in the query) or a typed one (CAST("doc" ->> 'Rank' AS integer)) got an index that applied cleanly, enforced uniqueness, and was never used by a single query. Members now render as Npgsql renders them — ->> or #>>, cast to the member's store type unless it is a string, decode(…, 'base64') for byte[], jsonb for a primitive collection or a json/jsonb member — in index parts, typed expression indexes and index filters. That also makes a filter such as x => x.Profile.Rank > 5 valid SQL: it compared text with an integer and failed at apply time. Default index names do not change. Upgrading: the first migrations add drops and re-creates each affected index under its existing name; indexes on top-level string members are untouched. Until that migration exists, has-pending-model-changes reports changes and Migrate() raises EF Core's pending-model-changes error. The re-create blocks writes while it builds, so on a large table declare the index with IsCreatedConcurrently() first. Exclusion constraint filters keep their rendering. The snapshot gains one CustomIndex:RenderingVersion annotation, which records the rules a model was declared under and is what lets the change reach databases built by earlier versions.
  • Changed: a non-unique index that starts with a date or time JSON member (DateTime, DateTimeOffset, DateOnly, TimeOnly) is rejected at migrations add. EF Core's queries cast such a member to timestamptz, date or time, and PostgreSQL cannot index those casts (the conversion from text is not IMMUTABLE), so no query could ever use the index. A unique one is still allowed and enforces uniqueness on the stored text; a member in a later position leaves the index usable through the parts before it.
  • Fixed: on PostgreSQL, a name this package introduces is checked against every object it shares a namespace with, at migrations add. PostgreSQL keeps constraint names unique per table and index names unique per schema — including the index behind every primary key, unique, exclusion and temporal constraint — but each kind was checked against its own kind on one table at most. Two temporal constraints with one name, a temporal foreign key named like a foreign key on its table, or a temporal constraint named like an index anywhere in the schema scaffolded cleanly and failed when applied (42710, 42P07). Against an exclusion constraint it did not even fail: every exclusion constraint is added after DROP CONSTRAINT IF EXISTS, so a same-named temporal constraint was dropped and the migration applied clean, one declared guarantee short. Two explicitly named complex indexes on different tables of one schema are caught the same way. A collision between two of EF Core's own objects is left to EF; a snapshot holding a collision stays diffable.

Published to nuget.org through Trusted Publishing by this run. The CycloneDX SBOM for each package is attached below.