EFCore.ComplexIndexes.SqlServer
5.5.0
dotnet add package EFCore.ComplexIndexes.SqlServer --version 5.5.0
NuGet\Install-Package EFCore.ComplexIndexes.SqlServer -Version 5.5.0
<PackageReference Include="EFCore.ComplexIndexes.SqlServer" Version="5.5.0" />
<PackageVersion Include="EFCore.ComplexIndexes.SqlServer" Version="5.5.0" />
<PackageReference Include="EFCore.ComplexIndexes.SqlServer" />
paket add EFCore.ComplexIndexes.SqlServer --version 5.5.0
#r "nuget: EFCore.ComplexIndexes.SqlServer, 5.5.0"
#:package EFCore.ComplexIndexes.SqlServer@5.5.0
#addin nuget:?package=EFCore.ComplexIndexes.SqlServer&version=5.5.0
#tool nuget:?package=EFCore.ComplexIndexes.SqlServer&version=5.5.0
EFCore.ComplexIndexes.SqlServer
On EF Core 11 or later? This package supports EF Core 10 only. From 5.5.0 it throws when you register it on any other major version. Its successor for EF Core 11 is a new package,
CodoMetis.EFCore.SchemaKit, tracked in #37.
SQL Server index options for EFCore.ComplexIndexes. This package brings the core package with it.
You get SQL Server's index options on indexes over complex properties:
- Clustered / nonclustered control
- Covering indexes (
INCLUDE) - Online index builds (
ONLINE = ON) - Fill factor
- Sort in tempdb
- Data compression (
ROW/PAGE)
Setup
Migrations need no setup. Every option goes into the migration as a SQL Server annotation that EF
Core's own SQL Server generator writes. Install the package, declare your indexes, and run
dotnet ef migrations add.
There is one optional call. Database.EnsureCreated(), GenerateCreateScript() and the
pending-model-changes check in Migrate() use your context's own services, which the automatic
design-time registration never reaches. Without a registration, EnsureCreated() creates the tables
and none of the indexes, with no error. Register the package once so these see your complex indexes
too:
options.UseSqlServer(connectionString).UseSqlServerComplexIndexes();
If you build your own internal service provider, call AddSqlServerComplexIndexes() on your
IServiceCollection instead.
Usage
builder.ComplexProperty(x => x.Email, c =>
c.Property(x => x.Value).HasColumnName("email"));
builder.HasComplexIndex(x => x.Email.Value, ix => ix
.IsUnique()
.HasName("ux_person_email")
.IncludeProperties("Name") // property paths resolve to columns
.IsCreatedOnline() // ONLINE = ON
.HasFillFactor(80));
// CREATE UNIQUE INDEX [ux_person_email] ON [person] ([email])
// INCLUDE ([name]) WITH (FILLFACTOR = 80, ONLINE = ON);
The builder also has IsClustered(), SortInTempDb() and
UseDataCompression(DataCompressionType.Page).
Filtered indexes (filter:) and DbOrder.Desc need nothing from this package, because EF Core's own
index operation carries both.
A filter can name properties instead of columns: migrations add turns
filter: "{DeletedAt} IS NULL" into [deleted_at] IS NULL.
Deliberate rejections
If you declare something SQL Server can't express, dotnet ef migrations add fails and names the
problem, instead of writing a migration that would fail when it runs:
- Expression parts. SQL Server has no DDL for an index on an expression. Store the expression in a persisted computed column and index that column instead.
DbOrder.NullsFirst/NullsLast. T-SQL has noNULLS FIRST/NULLS LAST.- A clustered index with
INCLUDEcolumns. Included columns belong to nonclustered indexes. A clustered index already stores every column. - A clustered filtered index. A filtered index must be nonclustered.
- A second clustered index on a table. Usually the primary key already holds the clustered slot:
SQL Server clusters the primary key unless you declare
HasKey(...).IsClustered(false). So that is normally what a clustered complex index collides with.
Documentation
- SQL Server — every index option and the declarations SQL Server can't express
- Full documentation
Changelog
This package's changelog, or the root changelog covering all three packages.
MIT licensed.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- EFCore.ComplexIndexes (= 5.5.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 10.0.0 && < 11.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
The last 5.x minor with a change of its own: the line refuses EF Core 11, whose successor is CodoMetis.EFCore.SchemaKit.SqlServer.
Changed answers
- Indexes: 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 (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/issues/88), Upgrading (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/docs/upgrading.md#unique-indexes-over-nullable-columns-on-sql-server)).
- Indexes: 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, and failed at apply with Msg 5074 (#142 (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/issues/142), Upgrading (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/docs/upgrading.md#include-entries-must-name-a-column)).
Breaking
- Registration: UseSqlServerComplexIndexes(), AddSqlServerComplexIndexes() and the design-time registration dotnet ef runs throw 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 (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/docs/upgrading.md#ef-core-11-is-refused-at-registration)).
- Indexes: on a database with a case-sensitive collation, complex index names that differ only in case fail at migrations add; rename one (Upgrading (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/docs/upgrading.md#rename-complex-index-names-that-differ-only-in-case)).
Changed
- 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 (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/issues/169)).
Fixed
- Indexes: 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 (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/docs/sqlserver.md#deliberate-rejections)).
- Indexes: 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 default collation compares them without regard to case (Index names (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/README.md#single-column-index-on-a-complex-property)).
- Migrations: a complex index renamed away from a name that the same migration gives to another index applies, where it failed at apply because the renamed index still held the name. It is dropped before EF Core's operations and created after them (Index names (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/README.md#single-column-index-on-a-complex-property)).
- Migrations: 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 (https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/docs/sqlserver.md)).
Full changelog: https://github.com/CaffeinatedCoder/EFCore.ComplexIndexes/blob/v5.5.0/src/EFCore.ComplexIndexes.SqlServer/CHANGELOG.md