Skip to content

v5.5.0

Choose a tag to compare

@github-actions github-actions released this 20 Oct 14:04
· 5 commits to main since this release
490b4de

The last 5.x minor with a change of its own: the line refuses EF Core 11, whose successor is CodoMetis.EFCore.SchemaKit. Some fixes change what an existing model scaffolds or applies: Changed answers in 5.5.0.

Changed answers

  • Registration: on SQL Server and PostgreSQL, the core differ refuses a complex index carrying that provider's index options and names UseSqlServerComplexIndexes() or UseNpgsqlComplexIndexes(). With UseComplexIndexes(), EnsureCreated() created the index without its property-level options (#92, Upgrading).
  • Registration: on PostgreSQL, the core differ also refuses exclusion constraints, temporal constraints and temporal foreign keys, and on SQL Server a unique complex index over nullable columns. With UseComplexIndexes(), EnsureCreated() created the tables without those constraints and the index without its IS NOT NULL filter (#150, Upgrading).
  • Indexes: on SQL Server, a unique complex index over nullable columns gets EF Core's IS NOT NULL filter, so rows without a value no longer collide. It admitted one such row and refused the second (#88, Upgrading).
  • Indexes: a complex index declared on a TPC type is created on the table of every type derived from it, as EF Core's own indexes are. On a concrete base it was created on the base's table only, so a unique index admitted duplicates among the derived types' rows (#93, Upgrading).
  • Indexes: a complex index with DbOrder.NullsFirst/NullsLast ordering or an expression part fails at migrations add on SQLite and other providers without a satellite, and under the core differ on SQL Server and PostgreSQL. Where SQLite accepts double-quoted strings, it applied with a constant column in place of its ordering or expression (#134, #172, Upgrading).
  • Indexes: on PostgreSQL and SQL Server, an IncludeProperties(…) entry that names neither a property nor a column of the table fails at migrations add. When its property was removed, the migration dropped only the column: PostgreSQL dropped the index with it and applied cleanly, SQL Server failed at apply (#142, Upgrading).
  • Expression indexes: on PostgreSQL, typed expression indexes and typed filters render Substring, Trim, TrimStart and TrimEnd as EF Core's queries do, so those queries can use the indexes. Trim() also trims tabs and line breaks, where it trimmed spaces only, so a typed filter can cover other rows: x.Code.Trim() != "" leaves out a tabs-only value (#72, Upgrading).
  • Expression indexes: on PostgreSQL, a typed expression index or filter wraps a concatenated operand that can be null in COALESCE(…, ''), as EF Core's queries do. x.Code + x.Suffix was NULL for every row without a suffix, so a unique index skipped those rows (#94, Upgrading).
  • Filters: on PostgreSQL, a typed filter keeps C#'s answer where an operand is null. x => x.Kind != "federated" on a string? covers the rows whose Kind is null, where it left them out, and a captured null compares with IS NULL, where it matched no row (#68, Upgrading).
  • Filters: on PostgreSQL, a brace in a string literal of a typed filter is compared as written. x => x.Code != "{draft}" renders '{draft}', where it rendered '{{draft}}' and kept the rows the filter excludes (#70, Upgrading).
  • Constraints: on PostgreSQL, an exclusion constraint, temporal constraint or temporal foreign key declared on a TPC type is added to the table of every type derived from it. On a concrete base it was added to the base's table only, and the derived tables accepted the overlapping rows it refuses (#93, Upgrading).
  • Migrations: on SQLite without UseComplexIndexes(), migrations add refuses a migration that rebuilds a table with a complex index, naming the indexes and the ways out. It scaffolded a migration that applied cleanly and dropped every complex index on the table (#86, Upgrading).
  • Migrations: on SQLite with UseComplexIndexes() after UseSqlite(), a migration that rebuilds a table drops its complex indexes before the rebuild and creates them after it. Applied without that registration, the migration fails before the rebuild (#95, Upgrading).

Breaking

  • Registration: every registration entry point, the design-time one dotnet ef runs included, throws InvalidOperationException on an EF Core major other than 10, naming CodoMetis.EFCore.SchemaKit for EF Core 11. EF Core 10 on .NET 11 keeps working (Upgrading).
  • Indexes: on a SQL Server database with a case-sensitive collation, or a provider without a satellite whose index names keep their case, complex index names that differ only in case fail at migrations add; rename one (Upgrading).
  • Indexes: a complex index, exclusion constraint or temporal constraint on a TPC type with derived types fails at migrations add when it reads a member of a complex property, which EF Core 10 maps to no column in a derived table; map the member as a regular property (Upgrading).
  • Constraints: on PostgreSQL, a temporal foreign key to a TPC type with derived types fails at migrations add, since its rows live in several tables; reference a type with no derived types (Upgrading).

Added

  • CustomMigrationsModelDiffer.RequiresIndexRecreation, a protected hook through which a provider's differ drops an unchanged complex index before a base operation that cannot run while it exists, and creates it after.
  • CustomMigrationsModelDiffer.ImplicitFilter, a protected hook through which a provider's differ gives an index declared without a filter the one its EF Core convention would give it.
  • CustomMigrationsModelDiffer.IndexNameComparer, a protected hook through which a provider's differ says how it compares index names: without regard to case by default and on SQL Server, ordinally on PostgreSQL.
  • CustomMigrationsModelDiffer(…, ICurrentDbContext), a constructor taking the context the migration is diffed for, and ComplexIndexAnnotations.AfterTableRebuild, the mark on a create that runs after SQLite's table rebuild (Upgrading).

Changed

  • Indexes: a complex index, exclusion constraint or temporal constraint declared on the abstract base of a TPC hierarchy is created on every concrete table, as EF Core's own indexes are, where it failed at migrations add (Upgrading).
  • Indexes: on PostgreSQL and SQLite, an explicit name on a TPC type's complex index, exclusion constraint or temporal constraint stays on that type's table, and each derived table's copy takes the name followed by its table. A copy's name past the identifier limit is shortened as EF Core's are, a temporal foreign key's too (#145, #167, #168, Upgrading).
  • Packaging: each package carries the version's section of its changelog as its NuGet release notes, which nuget.org's Release Notes tab and Visual Studio's Updates tab show.
  • Packaging: the release notes, the README on nuget.org and the GitHub release link the documentation at the version's tag, so they keep describing the version they shipped with after main moves on to the next line.
  • Packaging: the PostgreSQL and SQL Server packages depend on exactly their own version of EFCore.ComplexIndexes, and the core differ refuses a satellite of another version, naming both. Update the packages together: a 5.4.x satellite beside core 5.5.0 was refused as the core differ (#169).

Fixed

  • Indexes: on PostgreSQL, a complex index, exclusion constraint or temporal constraint named like a table, view or sequence of its schema, the sequence of an identity or serial column included, fails at migrations add, where it failed at apply with 42P07 (Index names).
  • Indexes: on SQL Server, a clustered complex index added in a later migration beside an existing one, and a complex index named like its table's primary key or a unique constraint, fail at migrations add, where they failed at apply (SQL Server).
  • Indexes: on SQLite and SQL Server, complex index names that differ only in case, from each other or from a native index, fail at migrations add, where they failed at apply because the database compares them without regard to case (Index names).
  • Expression indexes: on PostgreSQL, a typed expression index or filter refuses a member of a scalar type, such as CreatedAt.Year, at the declaration, where it failed at migrations add. .Value and .HasValue on a nullable translate (Typed expression indexes).
  • Filters: on PostgreSQL, a typed filter compares a char with a char literal, where it failed at apply on the char's code, and x.RevokedAt.HasValue renders IS NOT NULL, where it failed at migrations add (Typed filters).
  • Filters: on PostgreSQL, a filter of an index or exclusion constraint that compares a date or time ToJson() member with a column fails at migrations add, naming the member, where it failed at apply comparing text with a timestamp (JSON member indexes).
  • Constraints: on PostgreSQL, a migration that drops both tables of a temporal foreign key applies, Down() included, where it failed with 2BP01 when the principal's table sorted first (Temporal foreign keys).
  • Constraints: on PostgreSQL, an exclusion constraint filter on a ToJson() number, boolean, uuid or enum member casts it as EF Core's queries do and applies, where it failed with 42883 or 42804 (Exclusion constraints).
  • Constraints: on PostgreSQL, an exclusion constraint with a scalar element under gist gets btree_gist whatever the element's operator and however the method is spelled, so <> and UseMethod("GiST") apply, where they failed with 42704 when the extension was missing (Exclusion constraints).
  • Migrations: on SQL Server, changing the type, length or nullability of a column a complex index reads applies, an index renamed in the same migration included, where it failed with Msg 5074. The index is dropped before the ALTER COLUMN and created after it (SQL Server).
  • Migrations: on PostgreSQL and SQL Server, a complex index or constraint renamed away from a name the same migration gives to another object applies, where it failed because the renamed one still held the name. It is dropped before EF Core's operations and created after them, with any temporal foreign key referencing it (Index names).
  • Docs: the temporal foreign key samples pass both type arguments to HasTemporalForeignKey, and compile (Temporal foreign keys).
  • Docs: the PostgreSQL index guide says to pass a fractional storage parameter as a string, since Npgsql's generator formats numbers with the current culture (Index methods).

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