Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion entity-framework/core/modeling/indexes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Indexes - EF Core
description: Configuring indexes in an Entity Framework Core model
author: roji
ms.date: 10/1/2021
ms.date: 06/09/2026
uid: core/modeling/indexes
---
# Indexes
Expand Down Expand Up @@ -40,6 +40,58 @@ An index can also span more than one column:

Indexes over multiple columns, also known as *composite indexes*, speed up queries which filter on index's columns, but also queries which only filter on the *first* columns covered by the index. See the [performance docs](xref:core/performance/efficient-querying#use-indexes-properly) for more information.

## Indexes on complex type properties

Starting with EF Core 11.0, indexes can use scalar properties nested inside [complex types](xref:core/what-is-new/ef-core-10.0/whatsnew#complex-types):

```csharp
modelBuilder.Entity<Customer>()
.HasIndex(c => c.Address.PostalCode);
```

Composite indexes can mix regular entity properties and complex type properties:

```csharp
modelBuilder.Entity<Customer>()
.HasIndex(c => new { c.Region, c.Address.PostalCode });
```

The same paths can be specified by name:

```csharp
modelBuilder.Entity<Customer>()
.HasIndex("Address.PostalCode");
```

For complex types mapped to JSON columns, providers may also support indexing paths inside the JSON document:

```csharp
modelBuilder.Entity<Customer>()
.ComplexProperty(c => c.Address, b => b.ToJson());

modelBuilder.Entity<Customer>()
.HasIndex("Address.PostalCode");
```

Indexes over complex collections use collection path syntax. `[]` represents all elements, while `[0]`, `[1]`, and so on represent a specific element:
Comment thread
AndriySvyryd marked this conversation as resolved.

```csharp
modelBuilder.Entity<Order>()
.ComplexCollection(o => o.Items, b => b.ToJson());

modelBuilder.Entity<Order>()
.HasIndex("Items[].Sku");
```

The same index can be configured with a lambda expression using `Select`:

```csharp
modelBuilder.Entity<Order>()
.HasIndex(o => o.Items.Select(i => i.Sku));
```

Support for JSON-path indexes depends on the database provider. For example, the SQL Server provider creates SQL Server JSON indexes where supported, while the Azure Cosmos DB provider emits the configured paths into the container indexing policy.

## Index uniqueness

By default, indexes aren't unique: multiple rows are allowed to have the same value(s) for the index's column set. You can make an index unique as follows:
Expand Down Expand Up @@ -148,6 +200,14 @@ In the following example, the `Url` column is part of the index key, so any quer

[!code-csharp[Main](../../../samples/core/Modeling/IndexesAndConstraints/FluentAPI/IndexInclude.cs?name=IndexInclude&highlight=5-9)]

Starting with EF Core 11.0, SQL Server included columns can also refer to scalar properties nested inside complex types:

```csharp
modelBuilder.Entity<Customer>()
.HasIndex(c => c.Name)
.IncludeProperties(c => c.Address.City);
```

## Check constraints

Check constraints are a standard relational feature that allows you to define a condition that must hold for all rows in a table; any attempt to insert or modify data that violates the constraint will fail. Check constraints are similar to non-null constraints (which prohibit nulls in a column) or to unique constraints (which prohibit duplicates), but allow arbitrary SQL expression to be defined.
Expand Down
20 changes: 19 additions & 1 deletion entity-framework/core/modeling/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Keys - EF Core
description: How to configure keys for entity types when using Entity Framework Core
author: AndriySvyryd
ms.date: 10/14/2022
ms.date: 06/09/2026
uid: core/modeling/keys
---
# Keys
Expand Down Expand Up @@ -53,6 +53,24 @@ public class Car

***

## Keys on complex type properties

Starting with EF Core 11.0, keys can use scalar properties nested inside non-collection [complex types](xref:core/what-is-new/ef-core-10.0/whatsnew#complex-types).

```csharp
modelBuilder.Entity<Customer>()
.HasKey(c => c.CustomerId.Value);
```

The same path can be specified by name:

```csharp
modelBuilder.Entity<Customer>()
.HasKey("CustomerId.Value");
```

Complex properties on the path to a key property are required. Keys can't traverse complex collections or nullable complex properties.

## Value generation

For non-composite numeric and GUID primary keys, EF Core sets up value generation for you by convention. For example, a numeric primary key in SQL Server is automatically set up to be an IDENTITY column. For more information, see [the documentation on value generation](xref:core/modeling/generated-properties) and [guidance for specific inheritance mapping strategies](xref:core/modeling/inheritance#key-generation).
Expand Down
43 changes: 42 additions & 1 deletion entity-framework/core/providers/cosmos/modeling.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Modeling - Azure Cosmos DB Provider - EF Core
description: Configuring the model with the Azure Cosmos DB EF Core Provider
author: roji
ms.date: 09/26/2024
ms.date: 06/09/2026
uid: core/providers/cosmos/modeling
---
# Configuring the model with the EF Core Azure Cosmos DB Provider
Expand Down Expand Up @@ -67,6 +67,47 @@ If you don't configure a partition key with EF, a warning will be logged at star

Once your partition key properties are properly configured, you can provide values for them in queries; see [Querying with partition keys](xref:core/providers/cosmos/querying#partition-keys) for more information.

## Indexing policy

Starting with EF Core 11.0, the Azure Cosmos DB provider emits more of the EF model's index configuration into the container [indexing policy](/azure/cosmos-db/index-policy).

By default, Azure Cosmos DB automatically indexes all properties. You can configure this automatic indexing policy and exclude individual paths:

```csharp
modelBuilder.Entity<Order>()
.HasAutomaticIndexing()
.Except("/InternalNotes/?");
```

To index only explicitly configured paths, configure indexes with `HasIndex`. Automatic indexing is disabled automatically as soon as any single-property index is defined, so there is no need to call `HasAutomaticIndexing(false)` explicitly:

```csharp
modelBuilder.Entity<Order>(b =>
{
b.HasIndex(o => o.OrderNumber);
b.HasIndex(o => new { o.CustomerId, o.OrderDate });
});
```

When automatic indexing is enabled, single-property indexes are already covered by the default `/*` included path and aren't emitted separately. Composite, vector, and full-text indexes are always emitted.

Indexes can also traverse complex type properties and complex collections. In a string path, `[]` represents all elements of a collection:

```csharp
modelBuilder.Entity<Order>(b =>
{
b.ComplexCollection(o => o.Items);
b.HasIndex("Items[].Sku");
});
```

The same index can be configured with a lambda expression:

```csharp
modelBuilder.Entity<Order>()
.HasIndex(o => o.Items.Select(i => i.Sku));
```

## Discriminators

Since multiple entity types may be mapped to the same container, EF Core always adds a `$type` discriminator property to all JSON documents you save (this property was called `Discriminator` before EF 9.0); this allows EF to recognize documents being loaded from the database, and materialize the right .NET type. Developers coming from relational databases may be familiar with discriminators in the context of [table-per-hierarchy inheritance (TPH)](xref:core/modeling/inheritance#table-per-hierarchy-and-discriminator-configuration); in Azure Cosmos DB, discriminators are used not just in inheritance mapping scenarios, but also because the same container can contain completely different document types.
Expand Down
32 changes: 31 additions & 1 deletion entity-framework/core/providers/sql-server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Microsoft SQL Server Database Provider - EF Core
description: Documentation for the database provider that allows Entity Framework Core to be used with Microsoft SQL Server
author: AndriySvyryd
ms.date: 11/15/2021
ms.date: 06/09/2026
uid: core/providers/sql-server/index
---
# Microsoft SQL Server EF Core Database Provider
Expand Down Expand Up @@ -113,6 +113,36 @@ To configure EF with a compatibility level, use `UseCompatibilityLevel()` as fol
optionsBuilder.UseSqlServer("<CONNECTION STRING>", o => o.UseCompatibilityLevel(170));
```

## JSON indexes

Starting with EF Core 11.0, the SQL Server provider can create and scaffold [SQL Server JSON indexes](/sql/t-sql/statements/create-json-index-transact-sql) for paths inside complex types mapped to JSON columns.

For example, the following maps a complex type to a JSON column and creates a JSON index over a nested property:

```csharp
modelBuilder.Entity<Customer>()
.ComplexProperty(c => c.Contact, b => b.ToJson().HasColumnType("json"));

modelBuilder.Entity<Customer>()
.HasIndex("Contact.Address.City");
```

When SQL Server JSON indexes are supported, migrations generate SQL similar to:

```sql
CREATE JSON INDEX [IX_Customers_Contact_Address_City]
ON [Customers]([Contact]) FOR (N'$.Address.City');
```

Multiple paths inside the same JSON column can be indexed together:

```csharp
modelBuilder.Entity<Customer>()
.HasIndex(["Contact.Address.City", "Contact.PhoneNumber"]);
Comment thread
AndriySvyryd marked this conversation as resolved.
Comment thread
AndriySvyryd marked this conversation as resolved.
```

Paths through JSON arrays can use numeric indexers, for example `Orders[0].Number`. SQL Server JSON indexes don't support wildcard indexes over every array element.

## Connection resiliency

EF includes functionality for automatically retrying failed database commands; for more information, [see the documentation](xref:core/miscellaneous/connection-resiliency). When using <xref:Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseAzureSql*> and <xref:Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseAzureSynapse*>, connection resiliency is automatically set up with the appropriate settings specific for those databases. Otherwise, when using <xref:Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer*>, configure the provider with <xref:Microsoft.EntityFrameworkCore.Infrastructure.SqlEngineDbContextOptionsBuilder.EnableRetryOnFailure*> as shown in the connection resiliency documentation.
Expand Down
83 changes: 82 additions & 1 deletion entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: What's New in EF Core 11
description: Overview of new features in EF Core 11
author: roji
ms.date: 04/22/2026
ms.date: 06/09/2026
uid: core/what-is-new/ef-core-11.0/whatsnew
---

Expand Down Expand Up @@ -106,6 +106,39 @@ modelBuilder.Entity<MyEntity>()

This simplifies model configuration by removing the need to explicitly navigate through intermediate complex type builders to reach the property you want to configure.

<a name="complex-types-keys-indexes"></a>

### Keys and indexes on complex type properties

Keys and indexes can now use scalar properties nested inside non-collection complex types:

```csharp
modelBuilder.Entity<Customer>()
.HasKey(c => c.CustomerId.Value);

modelBuilder.Entity<Customer>()
.HasIndex(c => c.Address.PostalCode);
```

The same paths can be configured by name:

```csharp
modelBuilder.Entity<Customer>()
.HasIndex("Address.PostalCode");
```

For relational providers, indexes can also target paths inside complex types mapped to JSON columns. Complex collection paths use `[]` for all elements or a numeric indexer for a specific element:

```csharp
modelBuilder.Entity<Order>()
.ComplexCollection(o => o.Items, b => b.ToJson());

modelBuilder.Entity<Order>()
.HasIndex("Items[].Sku");
```

For more information, see [Keys](xref:core/modeling/keys#keys-on-complex-type-properties) and [Indexes](xref:core/modeling/indexes#indexes-on-complex-type-properties).

<a name="complex-types-stabilization"></a>

### Stabilization and bug fixes
Expand Down Expand Up @@ -508,6 +541,29 @@ WHERE JSON_CONTAINS([b].[JsonData], 8, N'$.Rating') = 1

For the full `JSON_CONTAINS` SQL Server documentation, see [`JSON_CONTAINS`](/sql/t-sql/functions/json-contains-transact-sql).

<a name="sqlserver-json-indexes"></a>

### JSON indexes

EF Core 11 can create and scaffold [SQL Server JSON indexes](/sql/t-sql/statements/create-json-index-transact-sql) for paths inside complex types mapped to JSON columns:

```csharp
modelBuilder.Entity<Customer>()
.ComplexProperty(c => c.Contact, b => b.ToJson().HasColumnType("json"));

modelBuilder.Entity<Customer>()
.HasIndex("Contact.Address.City");
```

This generates SQL similar to:

```sql
CREATE JSON INDEX [IX_Customers_Contact_Address_City]
ON [Customers]([Contact]) FOR (N'$.Address.City');
```

For more information, see [JSON indexes](xref:core/providers/sql-server/index#json-indexes).

<a name="sqlserver-temporal-clr-properties"></a>

### Temporal period properties mapped to CLR properties
Expand Down Expand Up @@ -602,6 +658,31 @@ Complex types are generally a better fit than owned types when mapping to JSON d

This feature was contributed by [@JoasE](https://github.com/JoasE) - many thanks!

<a name="cosmos-indexes"></a>

### Indexes and indexing policy

EF Core 11 adds support for more Azure Cosmos DB indexing policy configuration. You can now disable automatic indexing, exclude individual paths when automatic indexing is enabled, and emit explicit single-property, composite, vector, and full-text indexes:

```csharp
modelBuilder.Entity<Order>(b =>
{
b.HasAutomaticIndexing()
.Except("/InternalNotes/?");

b.HasIndex(o => new { o.CustomerId, o.OrderDate });
});
```

Indexes can also traverse complex type properties and complex collections:

```csharp
modelBuilder.Entity<Order>()
.HasIndex(o => o.Items.Select(i => i.Sku));
```

For more information, see [Indexing policy](xref:core/providers/cosmos/modeling#indexing-policy).

<a name="cosmos-transactional-batches"></a>

### Transactional batches
Expand Down
Loading