From f1961501f7dada2a9640697e109351d7d8bf3715 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 3 Jun 2026 18:31:33 +0200 Subject: [PATCH 01/19] Document EF Core 11 FullJoin support (#5374) Documents https://github.com/dotnet/efcore/issues/37633 --- .../providers/sql-server/vector-search.md | 31 +++++---- .../core/what-is-new/ef-core-11.0/whatsnew.md | 64 +++++++++++++++++++ 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/entity-framework/core/providers/sql-server/vector-search.md b/entity-framework/core/providers/sql-server/vector-search.md index 608ac0eb0b..8f16ea83fc 100644 --- a/entity-framework/core/providers/sql-server/vector-search.md +++ b/entity-framework/core/providers/sql-server/vector-search.md @@ -196,25 +196,30 @@ SqlVector queryEmbedding = ...; var results = await context.Articles // Perform full-text search .FreeTextTable(textualQuery, topN: k) + .Join( + context.Articles, + fts => fts.Key, + a => a.Id, + (fts, a) => new { Article = a, fts.Rank }) // Perform vector (semantic) search, joining the results of both searches together - .LeftJoin( + .FullJoin( context.Articles.VectorSearch(b => b.Embedding, queryEmbedding, "cosine") .OrderBy(r => r.Distance) .Take(k) .WithApproximate(), - fts => fts.Key, + fts => fts.Article.Id, vs => vs.Value.Id, (fts, vs) => new { - Article = vs.Value, - FullTextRank = fts.Rank, - VectorDistance = (double?)vs.Distance + Article = fts != null ? fts.Article : vs.Value, + FullTextRank = fts == null ? null : (int?)fts.Rank, + VectorDistance = vs == null ? null : (double?)vs.Distance }) // Apply Reciprocal Rank Fusion (RRF) to combine the results .Select(x => new { x.Article, - RrfScore = (1.0 / (k + x.FullTextRank)) + (1.0 / (k + x.VectorDistance) ?? 0.0) + RrfScore = (1.0 / (k + x.FullTextRank) ?? 0.0) + (1.0 / (k + x.VectorDistance) ?? 0.0) }) .OrderByDescending(x => x.RrfScore) .Take(10) @@ -225,19 +230,17 @@ var results = await context.Articles This query: 1. Performs a full-text search on `Article` -2. Performs a vector search on `Article` and combines the results to the full-text search results via a LEFT JOIN +2. Performs a vector search on `Article` and combines the results with the full-text search results via a FULL JOIN 3. Calculates the RRF score by combining both the full text and the semantic ranking 4. Orders by RRF score, takes the desired number of results and projects out the original `Article` entities. -> [!NOTE] -> Rather than using a LEFT JOIN, a FULL OUTER JOIN would be more suitable for this scenario; this would allow highly-ranking results from either search side to be included in the final result, even if that result does not appear at all on the other side. With the above LEFT JOIN approach, if a result has a very high vector similarity score, it never gets included in the final result if that result doesn't also have a high full-text score. However, EF doesn't currently support FULL OUTER JOIN; upvote [#37633](https://github.com/dotnet/efcore/issues/37633) if this is something you'd like to see supported. - The query produces the following SQL: ```sql -SELECT TOP(@__p_4) [a0].[Id], [a0].[Content], [a0].[Title] +SELECT TOP(@__p_4) COALESCE([a].[Id], [t].[Id]) AS [Id], COALESCE([a].[Content], [t].[Content]) AS [Content], COALESCE([a].[Title], [t].[Title]) AS [Title] FROM FREETEXTTABLE([Articles], *, @__textualQuery_0, @__k_1) AS [f] -LEFT JOIN ( +INNER JOIN [Articles] AS [a] ON [f].[KEY] = [a].[Id] +FULL JOIN ( SELECT TOP(@__k_1) WITH APPROXIMATE [a].[Id], [a].[Content], [a].[Title], [v].[Distance] FROM VECTOR_SEARCH( TABLE = [Articles] AS [a], @@ -246,6 +249,6 @@ LEFT JOIN ( METRIC = 'cosine' ) AS [v] ORDER BY [v].[Distance] -) AS [t] ON [f].[KEY] = [t].[Id] -ORDER BY 1.0E0 / CAST(@__k_1 + [f].[RANK] AS float) + ISNULL(1.0E0 / (CAST(@__k_1 AS float) + [t].[Distance]), 0.0E0) DESC +) AS [t] ON [a].[Id] = [t].[Id] +ORDER BY ISNULL(1.0E0 / CAST(@__k_1 + [f].[RANK] AS float), 0.0E0) + ISNULL(1.0E0 / (CAST(@__k_1 AS float) + [t].[Distance]), 0.0E0) DESC ``` diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index c49620df6d..9e8327235d 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -187,6 +187,30 @@ Both optimizations can have a significant positive impact on query performance, More details on the benchmark are available [here](https://github.com/dotnet/efcore/issues/29182#issuecomment-4231140289), and as always, actual performance in your application will vary based on your schema, data and a variety of other factors. + + +### Support for the new .NET 11 `FullJoin` operator + +.NET 11 adds first-class LINQ support for `FullJoin`, which keeps rows from both input collections and matches them when keys are equal. EF Core 11 translates this operator to `FULL JOIN` on relational databases: + +```csharp +var results = await context.Customers + .FullJoin( + context.Orders, + c => c.Id, + o => o.CustomerId, + (c, o) => new { Customer = c, Order = o }) + .ToListAsync(); +``` + +This generates SQL similar to the following: + +```sql +SELECT [c].[Id], [c].[Name], [o].[Id], [o].[CustomerId], [o].[OrderDate] +FROM [Customers] AS [c] +FULL JOIN [Orders] AS [o] ON [c].[Id] = [o].[CustomerId] +``` + ### Stripping of no-op CASTs @@ -374,6 +398,46 @@ Both methods return `FullTextSearchResult`, giving you access to both t For more information, see the [full documentation on full-text search](xref:core/providers/sql-server/full-text-search). + + +#### Hybrid search + +SQL Server vector search can be combined with full-text table-valued functions to implement _hybrid search_: full-text search finds exact linguistic matches, vector search finds semantically similar results, and the two rankings are merged. EF Core 11's `FullJoin` support makes this pattern more complete, since highly-ranked rows from either side can contribute to the final results: + +```csharp +var results = await context.Articles + .FreeTextTable(textualQuery, topN: k) + .Join( + context.Articles, + fts => fts.Key, + a => a.Id, + (fts, a) => new { Article = a, fts.Rank }) + .FullJoin( + context.Articles.VectorSearch(a => a.Embedding, queryEmbedding, "cosine") + .OrderBy(r => r.Distance) + .Take(k) + .WithApproximate(), + fts => fts.Article.Id, + vs => vs.Value.Id, + (fts, vs) => new + { + Article = fts != null ? fts.Article : vs.Value, + FullTextRank = fts == null ? null : (int?)fts.Rank, + VectorDistance = vs == null ? null : (double?)vs.Distance + }) + .Select(x => new + { + x.Article, + RrfScore = (1.0 / (k + x.FullTextRank) ?? 0.0) + (1.0 / (k + x.VectorDistance) ?? 0.0) + }) + .OrderByDescending(x => x.RrfScore) + .Take(10) + .Select(x => x.Article) + .ToListAsync(); +``` + +For more information, see the [SQL Server vector search documentation](xref:core/providers/sql-server/vector-search#hybrid-search). + ### Contains operations using JSON_CONTAINS From c742ccc76fc93e04558fb8a6c698940d9d529990 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Jun 2026 12:08:21 -0700 Subject: [PATCH 02/19] Document EF Core 11 indexing enhancements (#5380) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- entity-framework/core/modeling/indexes.md | 62 +++++++++++++- entity-framework/core/modeling/keys.md | 20 ++++- .../core/providers/cosmos/modeling.md | 43 +++++++++- .../core/providers/sql-server/index.md | 32 ++++++- .../core/what-is-new/ef-core-11.0/whatsnew.md | 83 ++++++++++++++++++- 5 files changed, 235 insertions(+), 5 deletions(-) diff --git a/entity-framework/core/modeling/indexes.md b/entity-framework/core/modeling/indexes.md index 003ca0c9cb..cd9a891175 100644 --- a/entity-framework/core/modeling/indexes.md +++ b/entity-framework/core/modeling/indexes.md @@ -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 @@ -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() + .HasIndex(c => c.Address.PostalCode); +``` + +Composite indexes can mix regular entity properties and complex type properties: + +```csharp +modelBuilder.Entity() + .HasIndex(c => new { c.Region, c.Address.PostalCode }); +``` + +The same paths can be specified by name: + +```csharp +modelBuilder.Entity() + .HasIndex("Address.PostalCode"); +``` + +For complex types mapped to JSON columns, providers may also support indexing paths inside the JSON document: + +```csharp +modelBuilder.Entity() + .ComplexProperty(c => c.Address, b => b.ToJson()); + +modelBuilder.Entity() + .HasIndex("Address.PostalCode"); +``` + +Indexes over complex collections use collection path syntax. `[]` represents all elements, while `[0]`, `[1]`, and so on represent a specific element: + +```csharp +modelBuilder.Entity() + .ComplexCollection(o => o.Items, b => b.ToJson()); + +modelBuilder.Entity() + .HasIndex("Items[].Sku"); +``` + +The same index can be configured with a lambda expression using `Select`: + +```csharp +modelBuilder.Entity() + .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: @@ -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() + .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. diff --git a/entity-framework/core/modeling/keys.md b/entity-framework/core/modeling/keys.md index bbb8ef5bec..72faa6419d 100644 --- a/entity-framework/core/modeling/keys.md +++ b/entity-framework/core/modeling/keys.md @@ -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 @@ -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() + .HasKey(c => c.CustomerId.Value); +``` + +The same path can be specified by name: + +```csharp +modelBuilder.Entity() + .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). diff --git a/entity-framework/core/providers/cosmos/modeling.md b/entity-framework/core/providers/cosmos/modeling.md index c3c5262536..2ea7c9e633 100644 --- a/entity-framework/core/providers/cosmos/modeling.md +++ b/entity-framework/core/providers/cosmos/modeling.md @@ -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 @@ -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() + .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(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(b => +{ + b.ComplexCollection(o => o.Items); + b.HasIndex("Items[].Sku"); +}); +``` + +The same index can be configured with a lambda expression: + +```csharp +modelBuilder.Entity() + .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. diff --git a/entity-framework/core/providers/sql-server/index.md b/entity-framework/core/providers/sql-server/index.md index 56d3210ba0..5512f5f984 100644 --- a/entity-framework/core/providers/sql-server/index.md +++ b/entity-framework/core/providers/sql-server/index.md @@ -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 @@ -113,6 +113,36 @@ To configure EF with a compatibility level, use `UseCompatibilityLevel()` as fol optionsBuilder.UseSqlServer("", 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() + .ComplexProperty(c => c.Contact, b => b.ToJson().HasColumnType("json")); + +modelBuilder.Entity() + .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() + .HasIndex(["Contact.Address.City", "Contact.PhoneNumber"]); +``` + +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 and , connection resiliency is automatically set up with the appropriate settings specific for those databases. Otherwise, when using , configure the provider with as shown in the connection resiliency documentation. diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index 9e8327235d..e6b7735c57 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -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 --- @@ -106,6 +106,39 @@ modelBuilder.Entity() This simplifies model configuration by removing the need to explicitly navigate through intermediate complex type builders to reach the property you want to configure. + + +### Keys and indexes on complex type properties + +Keys and indexes can now use scalar properties nested inside non-collection complex types: + +```csharp +modelBuilder.Entity() + .HasKey(c => c.CustomerId.Value); + +modelBuilder.Entity() + .HasIndex(c => c.Address.PostalCode); +``` + +The same paths can be configured by name: + +```csharp +modelBuilder.Entity() + .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() + .ComplexCollection(o => o.Items, b => b.ToJson()); + +modelBuilder.Entity() + .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). + ### Stabilization and bug fixes @@ -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). + + +### 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() + .ComplexProperty(c => c.Contact, b => b.ToJson().HasColumnType("json")); + +modelBuilder.Entity() + .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). + ### Temporal period properties mapped to CLR properties @@ -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! + + +### 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(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() + .HasIndex(o => o.Items.Select(i => i.Sku)); +``` + +For more information, see [Indexing policy](xref:core/providers/cosmos/modeling#indexing-policy). + ### Transactional batches From ccd214eecb0e06d5cc8601e04dbbddf1a4dd71f0 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:27:48 -0700 Subject: [PATCH 03/19] Document runtime migration creation (`--add` option for `database update`) (#5384) Fixes #5246 Co-authored-by: Andriy Svyryd --- entity-framework/core/cli/dotnet.md | 12 ++++++- entity-framework/core/cli/powershell.md | 9 ++++++ .../managing-schemas/migrations/managing.md | 31 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/entity-framework/core/cli/dotnet.md b/entity-framework/core/cli/dotnet.md index 1f0e66d35c..b0e20c4722 100644 --- a/entity-framework/core/cli/dotnet.md +++ b/entity-framework/core/cli/dotnet.md @@ -152,7 +152,10 @@ Options: | Option | Description | |:------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------| -| `--connection ` | The connection string to the database. Defaults to the one specified in `AddDbContext` or `OnConfiguring`. | +| `--connection ` | The connection string to the database. Defaults to the one specified in `AddDbContext` or `OnConfiguring`. | +| `--add` | Creates a new migration and applies it to the database in a single step. Uses Roslyn to compile the migration at runtime. When specified, the `` argument is required and provides the name for the new migration. | +| `--output-dir ` | The directory to put migration files in. Paths are relative to the target project directory. Requires `--add`. | +| `--namespace ` | The namespace to use for the generated migration classes. Requires `--add`. | The [common options](#common-options) are listed above. @@ -163,6 +166,13 @@ dotnet ef database update InitialCreate dotnet ef database update 20180904195021_InitialCreate --connection your_connection_string ``` +The following examples create a new migration and apply it to the database in one step: + +```dotnetcli +dotnet ef database update InitialCreate --add +dotnet ef database update AddProducts --add --output-dir Migrations/Products --namespace MyApp.Migrations +``` + ## `dotnet ef dbcontext info` Gets information about a `DbContext` type. diff --git a/entity-framework/core/cli/powershell.md b/entity-framework/core/cli/powershell.md index 8868bcd962..a7eab8b740 100644 --- a/entity-framework/core/cli/powershell.md +++ b/entity-framework/core/cli/powershell.md @@ -316,6 +316,9 @@ Updates the database to the last migration or to a specified migration. |:------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `-Migration ` | The target migration. Migrations may be identified by name or by ID. The number 0 is a special case that means *before the first migration* and causes all migrations to be reverted. If no migration is specified, the command defaults to the last migration. | | `-Connection ` | The connection string to the database. Defaults to the one specified in `AddDbContext` or `OnConfiguring`. | +| `-Add` | Creates a new migration and applies it to the database in a single step. Uses Roslyn to compile the migration at runtime. When specified, a migration name is required and provides the name for the new migration. | +| `-OutputDir ` | The directory to put migration files in. Paths are relative to the target project directory. Requires `-Add`. | +| `-Namespace ` | The namespace to use for the generated migration classes. Requires `-Add`. | The [common parameters](#common-parameters) are listed above. @@ -335,6 +338,12 @@ Update-Database InitialCreate Update-Database 20180904195021_InitialCreate -Connection your_connection_string ``` +The following example creates a new migration and applies it to the database in one step: + +```powershell +Update-Database -Migration InitialCreate -Add +``` + ## Additional resources * [Migrations](xref:core/managing-schemas/migrations/index) diff --git a/entity-framework/core/managing-schemas/migrations/managing.md b/entity-framework/core/managing-schemas/migrations/managing.md index 2f903799bd..574999e5d3 100644 --- a/entity-framework/core/managing-schemas/migrations/managing.md +++ b/entity-framework/core/managing-schemas/migrations/managing.md @@ -65,6 +65,37 @@ Add-Migration InitialCreate -OutputDir Your\Directory *** +## Create and apply a migration in one step + +> [!NOTE] +> This feature was added in EF Core 11. + +The `dotnet ef database update` command supports creating and applying a migration in a single step using the `--add` option. This uses Roslyn to compile the migration at runtime, enabling scenarios like .NET Aspire and containerized applications where the application cannot be stopped and rebuilt: + +### [.NET CLI](#tab/dotnet-core-cli) + +```dotnetcli +dotnet ef database update InitialCreate --add +``` + +The same options available for `dotnet ef migrations add` can be used: + +```dotnetcli +dotnet ef database update AddProducts --add --output-dir Migrations/Products --namespace MyApp.Migrations +``` + +### [Visual Studio](#tab/vs) + +```powershell +Update-Database -Migration InitialCreate -Add +``` + +*** + +This command scaffolds a new migration with the specified name, compiles it using Roslyn, and immediately applies it to the database. The migration files are still saved to disk for source control and future recompilation. + +If no pending model changes are detected, the command applies any existing pending migrations without creating a new one. + ## Customize migration code While EF Core generally creates accurate migrations, you should always review the code and make sure it corresponds to the desired change; in some cases, it is even necessary to do so. From 229845183147ab7b2025e0a354e296011ca82671 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:36:45 -0700 Subject: [PATCH 04/19] Document obsoletion of owned JSON collections without an explicit key (EF11) (#5383) Fixes #5238 Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../ef-core-11.0/breaking-changes.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index d2b096990e..7ca9c670be 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -30,6 +30,7 @@ This page documents API and behavior changes that have the potential to break ex | [EF tools packages no longer reference Microsoft.EntityFrameworkCore.Design](#ef-tools-no-design-dep) | Low | | [SqlVector properties are no longer loaded by default](#sqlvector-not-auto-loaded) | Low | | [Cosmos: empty owned collections now return an empty collection instead of null](#cosmos-empty-collections) | Low | +| [Owned JSON collections without an explicit key are obsolete](#owned-json-collections-obsolete) | Low | ## Medium-impact changes @@ -321,6 +322,78 @@ if (entity.OwnedCollection is { Count: 0 }) } ``` + + +### Owned JSON collections without an explicit key are obsolete + +[Tracking Issue #37289](https://github.com/dotnet/efcore/issues/37289) + +#### Old behavior + +Previously, owned entity types mapped to a JSON column via could be used as collections without configuring an explicit primary key. EF Core would synthesize an ordinal (positional) key behind the scenes to identify each item in the collection: + +```csharp +public class Blog +{ + public int Id { get; set; } + public List Posts { get; set; } = new(); +} + +public class Post +{ + // No key property + public required string Title { get; set; } + public required string Content { get; set; } +} + +protected override void OnModelCreating(ModelBuilder modelBuilder) + => modelBuilder.Entity().OwnsMany(b => b.Posts, b => b.ToJson()); +``` + +#### New behavior + +Starting with EF Core 11.0, configuring an owned JSON collection without an explicit key produces an `OwnedEntityMappedToJsonCollectionWarning` warning. The mapping continues to work, but is now considered deprecated and is expected to be removed in a future release. + +Owned JSON entities that have an explicit primary key, as well as non-collection owned JSON references, are not affected by this change. + +#### Why + +[Complex types](xref:core/what-is-new/ef-core-10.0/whatsnew#complex-types) became fully supported in EF Core 10, including for [JSON mapping](xref:core/what-is-new/ef-core-10.0/whatsnew#json). Complex types are a better fit than owned types for JSON documents: they have value semantics and no identity, which avoids many of the issues that come from using owned entity types—which are entity types—to model what is fundamentally a value embedded in another document. In particular, owned JSON collections without an explicit key relied on a synthetic ordinal key, which has known limitations and corner cases. + +#### Mitigations + +The recommended mitigation is to migrate the type to a complex type, which is now the preferred way to map types to JSON: + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) + => modelBuilder.Entity().ComplexCollection(b => b.Posts, b => b.ToJson()); +``` + +Alternatively, if you need to keep the owned-type mapping, configure a non-shadow primary key on the owned type. Once a key is configured, the warning no longer applies: + +```csharp +public class Post +{ + public int Id { get; set; } + public required string Title { get; set; } + public required string Content { get; set; } +} + +protected override void OnModelCreating(ModelBuilder modelBuilder) + => modelBuilder.Entity().OwnsMany(b => b.Posts, b => + { + b.ToJson(); + b.HasKey(p => p.Id); + }); +``` + +If you cannot migrate immediately, you can suppress the warning via `ConfigureWarnings`: + +```csharp +protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.OwnedEntityMappedToJsonCollectionWarning)); +``` + ## Microsoft.Data.Sqlite breaking changes From 056e4e68d30442c909f542b7190a345ddab20be3 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:38:17 -0700 Subject: [PATCH 05/19] Add docs for the remaining preview 6 features (#5382) --- .../core/learn-more/community-standups.md | 2 +- .../core/providers/sqlite/functions.md | 2 + .../ef-core-11.0/breaking-changes.md | 2 +- .../core/what-is-new/ef-core-11.0/whatsnew.md | 61 ++++++++++++++++++- .../ef-core-6.0/breaking-changes.md | 2 +- 5 files changed, 65 insertions(+), 4 deletions(-) diff --git a/entity-framework/core/learn-more/community-standups.md b/entity-framework/core/learn-more/community-standups.md index d53d04be43..eac4c81958 100644 --- a/entity-framework/core/learn-more/community-standups.md +++ b/entity-framework/core/learn-more/community-standups.md @@ -420,7 +420,7 @@ Featuring: Links: - Product: [Hot Chocolate for GraphQL](https://chillicream.com/docs/hotchocolate) -- Docs: [Hot Chocolate and Entity Framework Core](https://chillicream.com/docs/hotchocolate/integrations/entity-framework) +- Docs: [Hot Chocolate and Entity Framework Core](https://chillicream.com/docs/hotchocolate/v14/integrations/entity-framework) diff --git a/entity-framework/core/providers/sqlite/functions.md b/entity-framework/core/providers/sqlite/functions.md index bcc0c1e3a4..6725219b68 100644 --- a/entity-framework/core/providers/sqlite/functions.md +++ b/entity-framework/core/providers/sqlite/functions.md @@ -22,7 +22,9 @@ group.Min(x => x.Property) | MIN(Property) group.Sum(x => x.Property) | SUM(Property) group.Sum(x => x.DecimalProperty) | ef_sum(DecimalProperty) | EF Core 9.0 string.Concat(group.Select(x => x.Property)) | group_concat(Property, '') +string.Concat(group.OrderBy(x => x.Other).Select(x => x.Property)) | group_concat(Property, '' ORDER BY Other) | EF Core 11.0 string.Join(separator, group.Select(x => x.Property)) | group_concat(Property, @separator) +string.Join(separator, group.OrderBy(x => x.Other).Select(x => x.Property)) | group_concat(Property, @separator ORDER BY Other) | EF Core 11.0 ## Binary functions diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 7ca9c670be..42048a9f28 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -123,7 +123,7 @@ If your application uses composite keys whose values can contain the characters - **Existing data**: Documents previously stored in Cosmos DB have `id` values using the old escape sequences (e.g. `Post|1|^2F`). After upgrading to EF Core 11, EF will generate unescaped `id` values (e.g. `Post|1|/`) and will no longer find those existing documents. To continue accessing existing data without migration, opt back into the old behavior using the `AppContext` switch described above—however, be aware that the id-collision bug will still be present. -- **New data**: If you are creating a new application or database, avoid using these illegal characters in key values, as they are not valid in Cosmos DB resource `id` values. See the [Azure documentation](https://learn.microsoft.com/dotnet/api/microsoft.azure.documents.resource.id) for details. +- **New data**: If you are creating a new application or database, avoid using these illegal characters in key values, as they are not valid in Cosmos DB resource `id` values. See the [Azure documentation](/dotnet/api/microsoft.azure.documents.resource.id) for details. ## Low-impact changes diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index e6b7735c57..8313236d2b 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -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: 06/09/2026 +ms.date: 06/10/2026 uid: core/what-is-new/ef-core-11.0/whatsnew --- @@ -624,6 +624,48 @@ For the complete list of date/time function translations, see the [SQL Server fu * now defaults to compatibility level 160 (SQL Server 2022), enabling SQL Server 2022-specific translations such as `LEAST` and `GREATEST` by default; see the [breaking change note](xref:core/what-is-new/ef-core-11.0/breaking-changes#sqlserver-compatibility-level-160) for more information. +## SQLite + + + +### Ordering in string aggregation + +EF Core can translate `string.Join` and `string.Concat` over a grouping to SQLite's `group_concat` aggregate function. Starting with EF 11, these translations also support ordering the aggregated values, by applying `OrderBy`/`OrderByDescending` inside the aggregate. Previously, queries that ordered the values fell back to client evaluation. + +For example, the following query concatenates each blog's post titles, ordered by descending post `Id`: + +```csharp +var blogs = await context.Blogs + .Select(b => new + { + b.Name, + Posts = string.Join( + ", ", + b.Posts.OrderByDescending(p => p.Id).Select(p => p.Title)) + }) + .ToListAsync(); +``` + +This translates to the following SQL, which uses `group_concat` with an `ORDER BY` clause: + +```sql +SELECT "b"."Name", COALESCE(group_concat("p"."Title", ', ' ORDER BY "p"."Id" DESC), '') AS "Posts" +FROM "Blogs" AS "b" +LEFT JOIN "Posts" AS "p" ON "b"."Id" = "p"."BlogId" +GROUP BY "b"."Id", "b"."Name" +``` + +Ordering inside `group_concat` requires SQLite 3.44.0 or later. + + + +### UInt128 support + +`Microsoft.Data.Sqlite` can now bind parameter values. The value is stored as a zero-padded, 39-digit text representation, which preserves correct ordering and comparison of values directly in the database. + +> [!NOTE] +> Reading values from data readers is not yet supported. + ## Cosmos DB @@ -856,6 +898,23 @@ Explicit command-line options always take precedence over configuration file val For more information, see [Configuration file](xref:core/cli/dotnet#configuration-file). + + +### Wildcard context support for migration commands + +When a project defines multiple `DbContext` types, several `dotnet ef` commands accept a wildcard (`*`) as the value of the `--context` option to target all contexts at once, instead of running the command separately for each one. The commands that support the wildcard are: + +* `dotnet ef migrations list` — lists the migrations for every context. +* `dotnet ef migrations script` — generates and concatenates a script for every context. +* `dotnet ef database update` — applies migrations to the database of every context (migration bundles are covered as well). +* `dotnet ef database drop` — drops the database for every context. + +For example, the following command lists the migrations for all contexts in the project: + +```dotnetcli +dotnet ef migrations list --context "*" +``` + ## Other improvements * The EF command-line tool now writes all logging and status messages to standard error, reserving standard output only for the command's actual expected output. For example, when generating a migration SQL script with `dotnet ef migrations script`, only the SQL is written to standard output. diff --git a/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md index b8ab08ccfc..7f2dab4891 100644 --- a/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md @@ -428,7 +428,7 @@ If your application expects joined entities to be returned in a particular order #### Why - was originally made to implement mainly in order to allow direct enumeration on it via the `foreach` construct. Unfortunately, when a project also references [System.Linq.Async](https://www.nuget.org/packages/System.Linq.Async) in order to compose async LINQ operators client-side, this resulted in an ambiguous invocation error between the operators defined over `IQueryable` and those defined over `IAsyncEnumerable`. C# 9 added [extension `GetEnumerator` support for `foreach` loops](/dotnet/csharp/language-reference/proposals/csharp-9.0/extension-getenumerator), removing the original main reason to reference `IAsyncEnumerable`. + was originally made to implement mainly in order to allow direct enumeration on it via the `foreach` construct. Unfortunately, when a project also references [System.Linq.Async](https://www.nuget.org/packages/System.Linq.Async) in order to compose async LINQ operators client-side, this resulted in an ambiguous invocation error between the operators defined over `IQueryable` and those defined over `IAsyncEnumerable`. C# 9 added [extension `GetEnumerator` support for `foreach` loops](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-9.0/extension-getenumerator.md), removing the original main reason to reference `IAsyncEnumerable`. The vast majority of `DbSet` usages will continue to work as-is, since they compose LINQ operators over `DbSet`, enumerate it, etc. The only usages broken are those which attempt to cast `DbSet` directly to `IAsyncEnumerable`. From ebc3911064fba85a25f1e0558ab65b7c4716e9df Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:48:08 +0200 Subject: [PATCH 06/19] Document Cosmos discriminator naming breaking change (EF Core 11) (#5391) * Document Cosmos discriminator naming breaking change for EF Core 11 * Address review: relabel PR link and split note sentence * docs: adjust Cosmos discriminator wording * docs: clarify discriminator rename examples * docs: clarify discriminator example intent --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .../core/providers/cosmos/modeling.md | 11 +++- .../ef-core-11.0/breaking-changes.md | 58 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/entity-framework/core/providers/cosmos/modeling.md b/entity-framework/core/providers/cosmos/modeling.md index 2ea7c9e633..2bfa8608d3 100644 --- a/entity-framework/core/providers/cosmos/modeling.md +++ b/entity-framework/core/providers/cosmos/modeling.md @@ -110,7 +110,7 @@ modelBuilder.Entity() ## 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. +Since multiple entity types may be mapped to the same container, EF Core always adds a discriminator property to all JSON documents you save (mapped as `$type`); 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. The discriminator property name and values can be configured with the standard EF APIs, [see these docs for more information](xref:core/modeling/inheritance). If you're mapping a single entity type to a container, are confident that you'll never be mapping another one, and would like to get rid of the discriminator property, call [HasNoDiscriminator](/dotnet/api/Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.HasNoDiscriminator): @@ -118,6 +118,15 @@ The discriminator property name and values can be configured with the standard E modelBuilder.Entity().HasNoDiscriminator(); ``` +> [!NOTE] +> Starting with EF Core 11.0, the discriminator property is named `Discriminator` in the EF model. The property written to the JSON document is still named `$type` by default. To change the name used in the JSON documents for the whole model in a single place--for example, to align it with the model property name--use : +> +> ```csharp +> modelBuilder.HasEmbeddedDiscriminatorName("Discriminator"); +> ``` +> +> See the [EF Core 11.0 breaking changes](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-discriminator-property-name) for more details. + Since the same container can contain different entity types, and the JSON `id` property must be unique within a container partition, you cannot have the same `id` value for entities of different types in the same container partition. Compare this to relational databases, where each entity type is mapped to a different table, and therefore has its own, separate key space. It is therefore your responsibility to ensure the `id` uniqueness of documents you insert into a container. If you need to have different entity types with the same primary key values, you can instruct EF to automatically insert the discriminator into the `id` property as follows: ```csharp diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 42048a9f28..bc1ce6aca1 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -30,6 +30,7 @@ This page documents API and behavior changes that have the potential to break ex | [EF tools packages no longer reference Microsoft.EntityFrameworkCore.Design](#ef-tools-no-design-dep) | Low | | [SqlVector properties are no longer loaded by default](#sqlvector-not-auto-loaded) | Low | | [Cosmos: empty owned collections now return an empty collection instead of null](#cosmos-empty-collections) | Low | +| [Cosmos: the default discriminator property is now named `Discriminator` in the model](#cosmos-discriminator-property-name) | Low | | [Owned JSON collections without an explicit key are obsolete](#owned-json-collections-obsolete) | Low | ## Medium-impact changes @@ -322,6 +323,63 @@ if (entity.OwnedCollection is { Count: 0 }) } ``` + + +### Cosmos: the default discriminator property is now named `Discriminator` in the model + +[Pull Request #38458](https://github.com/dotnet/efcore/pull/38458) + +#### Old behavior + +EF automatically adds a discriminator property to identify the entity type that a JSON document represents. The name of this property in the JSON document was changed from `Discriminator` to `$type` in [EF Core 9.0](xref:core/what-is-new/ef-core-9.0/breaking-changes#cosmos-discriminator-name-change). To achieve this, EF used `$type` as the name of the discriminator property both in the EF model and in the stored JSON document. + +Because `$type` is not a valid C# identifier, the resulting shadow property name caused invalid code to be generated for [compiled models](xref:core/performance/advanced-performance-topics#compiled-models) and [precompiled queries](xref:core/performance/nativeaot-and-precompiled-queries) used with Native AOT. + +#### New behavior + +Starting with EF Core 11.0, the default discriminator property is once again named `Discriminator` in the EF model, while the name written to the JSON document is unchanged and remains `$type` by default. In other words, the model property name and the JSON property name are now decoupled: + +- `entityType.FindDiscriminatorProperty().Name` returns `Discriminator`. +- `entityType.FindDiscriminatorProperty().GetJsonPropertyName()` returns `$type`. + +The format of the stored documents is **not** affected by this change, so existing data continues to work without modification. + +#### Why + +EF derives some generated C# identifiers (for example, shadow property variable names) from model metadata such as property names. Since `$type` is not a valid C# identifier, using it as the model property name produced uncompilable code for compiled models and precompiled queries. Naming the model property `Discriminator` (a valid identifier) while still writing `$type` to the document keeps generated code valid without changing the on-disk format. + +#### Mitigations + +For most applications no action is needed, since stored documents are unaffected and continue to use `$type`. + +If your code references the discriminator by its **model** property name, `$type` (for example, via in a query or query filter, or by looking the property up in the metadata), update it to use `Discriminator` instead: + +```csharp +// Before +var query = context.Set().Where(e => EF.Property(e, "$type") == "Lecture"); + +// After +var query = context.Set().Where(e => EF.Property(e, "Discriminator") == "Lecture"); +``` + +To change the JSON discriminator property name for the whole model in a single place--for example, to align it with the model property name--use the model-level API instead of configuring each entity type individually: + +```csharp +modelBuilder.HasEmbeddedDiscriminatorName("Discriminator"); +``` + +To change only the JSON name for a specific entity type--for example, to align it with the model property name--configure the discriminator property's JSON name with : + +```csharp +modelBuilder.Entity().Property("Discriminator").ToJsonProperty("Discriminator"); +``` + +To restore the previous behavior where the discriminator property is also named `$type` in the model, configure its name explicitly with . Note that this reintroduces an invalid C# identifier and is not recommended when using compiled models or precompiled queries: + +```csharp +modelBuilder.Entity().HasDiscriminator("$type"); +``` + ### Owned JSON collections without an explicit key are obsolete From 92a1a79c40c20358a4d2ade42311471e2fee1c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Cincura=20=E2=86=B9?= Date: Wed, 24 Jun 2026 17:29:40 +0200 Subject: [PATCH 07/19] Fix link. (#5393) --- .../core/what-is-new/ef-core-11.0/breaking-changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index bc1ce6aca1..97a5dad5e3 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -388,7 +388,7 @@ modelBuilder.Entity().HasDiscriminator("$type"); #### Old behavior -Previously, owned entity types mapped to a JSON column via could be used as collections without configuring an explicit primary key. EF Core would synthesize an ordinal (positional) key behind the scenes to identify each item in the collection: +Previously, owned entity types mapped to a JSON column via could be used as collections without configuring an explicit primary key. EF Core would synthesize an ordinal (positional) key behind the scenes to identify each item in the collection: ```csharp public class Blog From 33cef5819d96fe9d1409a3c9b39597bf93ebe103 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 10:50:32 +0200 Subject: [PATCH 08/19] Add EF11 breaking change note: `Property` no longer configures primitive collections (#5399) * Add breaking change note for primitive collection configuration (efcore#38484) * Remove tracking issue link from primitive collection breaking change section --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .../ef-core-11.0/breaking-changes.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 97a5dad5e3..a1e73a285a 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -32,6 +32,7 @@ This page documents API and behavior changes that have the potential to break ex | [Cosmos: empty owned collections now return an empty collection instead of null](#cosmos-empty-collections) | Low | | [Cosmos: the default discriminator property is now named `Discriminator` in the model](#cosmos-discriminator-property-name) | Low | | [Owned JSON collections without an explicit key are obsolete](#owned-json-collections-obsolete) | Low | +| [`Property` no longer configures primitive collections](#property-not-primitive-collection) | Low | ## Medium-impact changes @@ -452,6 +453,33 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.OwnedEntityMappedToJsonCollectionWarning)); ``` + + +### `Property` no longer configures primitive collections + +#### Old behavior + +Previously, calling for a member whose CLR type is a collection (for example `List`) could result in the member being configured as a [primitive collection](xref:core/what-is-new/ef-core-8.0/whatsnew#primitive-collections), because a property could be promoted to a primitive collection at model finalization based on its type. + +#### New behavior + +Starting with EF Core 11.0, whether a property is a primitive collection is determined entirely when the property is configured. A primitive collection must be configured with (or discovered as one by convention). now always configures the member as a non-collection (scalar) property, and there is no longer any finalization-time promotion to a primitive collection. + +#### Why + +Treating the element type as a finalization-time concern led to inconsistencies and bugs. For example, a property could be discovered as a primitive collection, but later resolve to a scalar via an inherited value converter, leaving a stale element type that caused an `InvalidCastException` at model finalization. Making primitive collections a creation-time concern also makes mapping unambiguous in cases like `byte[]`, where it is otherwise unclear whether the member should be mapped as a binary scalar or as a collection of bytes. + +#### Mitigations + +If you relied on `Property` to configure a primitive collection, switch to `PrimitiveCollection` instead: + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) + => modelBuilder.Entity().PrimitiveCollection(b => b.Tags); +``` + +In most cases no change is required, since primitive collections are discovered by convention. + ## Microsoft.Data.Sqlite breaking changes From 34efc7d412abe4f0e852975700d5c68eb5d033cd Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:46:18 +0200 Subject: [PATCH 09/19] Document Microsoft.Data.Sqlite .NET Framework support removal in EF Core 11 breaking changes (#5411) --- .../ef-core-11.0/breaking-changes.md | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index a1e73a285a..718a6c9131 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -2,7 +2,7 @@ title: Breaking changes in EF Core 11 (EF11) - EF Core description: List of breaking changes introduced in Entity Framework Core 11 (EF11) author: roji -ms.date: 03/27/2026 +ms.date: 07/02/2026 uid: core/what-is-new/ef-core-11.0/breaking-changes --- @@ -491,11 +491,36 @@ In most cases no change is required, since primitive collections are discovered | **Breaking change** | **Impact** | |:----------------------------------------------------------------------------------------------------------|------------| +| [Microsoft.Data.Sqlite no longer supports .NET Framework](#sqlite-no-netfx) | Medium | | [Encryption-enabled SQLite packages have been removed](#sqlite-encryption-removed) | Medium | | [Some SQLitePCLRaw bundle packages have been removed](#sqlite-bundles-removed) | Medium | ### Medium-impact changes + + +#### Microsoft.Data.Sqlite no longer supports .NET Framework + +[Tracking Issue #35599](https://github.com/dotnet/efcore/issues/35599) + +##### Old behavior + +Previously, `Microsoft.Data.Sqlite` and `Microsoft.Data.Sqlite.Core` targeted `netstandard2.0`, which allowed them to be used from .NET Framework applications. + +##### New behavior + +Starting with `Microsoft.Data.Sqlite` 11.0, both packages target `net10.0` only. .NET Framework applications can no longer reference or use `Microsoft.Data.Sqlite` 11.0. + +##### Why + +The `netstandard2.0` target made older, unsupported .NET targets appear to be supported, and it also masked API differences such as `DateOnly` and `TimeOnly` support. Targeting the minimum supported .NET version explicitly makes the supported platform surface clear. + +##### Mitigations + +If possible, move the application to .NET 10 or later. + +If you must remain on .NET Framework, stay on the latest `Microsoft.Data.Sqlite` 10.0.x servicing release. The 10.0.x line already uses `SQLite3MC.PCLRaw.bundle`, allowing .NET Framework applications to update the referenced `SQLite3MC.PCLRaw.bundle` version even after `Microsoft.Data.Sqlite` stops receiving updated. + #### Encryption-enabled SQLite packages have been removed From 033a6bd48f19a162d83df29ba3192332b07725fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Jul 2026 21:16:17 +0000 Subject: [PATCH 10/19] Initial plan From 43f38e18ecf18829366827ee58e5939886577e3a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:24:37 +0200 Subject: [PATCH 11/19] Revert EF11 SQLite breaking changes for bundle_e_sqlite3 2.1.12 (#5425) * Update EF11 SQLite breaking changes for bundle_e_sqlite3 2.1.12 revert * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Restore deprecated SQLitePCLRaw bundle packages section, merged with encryption content * Clarify scope of deprecated bundle packages breaking change * Move UWP/Xamarin to Low impact, update Why text, fix bundle Old behavior text --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Andriy Svyryd Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../ef-core-11.0/breaking-changes.md | 129 ++++-------------- 1 file changed, 30 insertions(+), 99 deletions(-) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 7c1cbf07e4..f4e3c56230 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -491,9 +491,8 @@ In most cases no change is required, since primitive collections are discovered | **Breaking change** | **Impact** | |:----------------------------------------------------------------------------------------------------------|------------| | [Microsoft.Data.Sqlite no longer supports .NET Framework](#sqlite-no-netfx) | Medium | -| [Encryption-enabled SQLite packages have been removed](#sqlite-encryption-removed) | Medium | -| [Some SQLitePCLRaw bundle packages have been removed](#sqlite-bundles-removed) | Medium | -| [Microsoft.Data.Sqlite now bundles SQLite3 Multiple Ciphers](#sqlite3mc) | Low | +| [Some SQLitePCLRaw bundle packages are no longer maintained](#sqlite-bundles-deprecated) | Medium | +| [SQLite no longer supports UWP and classic Xamarin](#sqlite-no-uwp-xamarin) | Low | ### Medium-impact changes @@ -519,58 +518,44 @@ The `netstandard2.0` target made older, unsupported .NET targets appear to be su If possible, move the application to .NET 10 or later. -If you must remain on .NET Framework, stay on the latest `Microsoft.Data.Sqlite` 10.0.x servicing release. The 10.0.x line already uses `SQLite3MC.PCLRaw.bundle`, allowing .NET Framework applications to update the referenced `SQLite3MC.PCLRaw.bundle` version even after `Microsoft.Data.Sqlite` stops receiving updates. +If you must remain on .NET Framework, stay on the latest `Microsoft.Data.Sqlite` 10.0.x servicing release. The 10.0.x line uses `SQLitePCLRaw.bundle_e_sqlite3`, allowing .NET Framework applications to update the referenced `SQLitePCLRaw.bundle_e_sqlite3` version even after `Microsoft.Data.Sqlite` stops receiving updates. - + -#### Encryption-enabled SQLite packages have been removed +#### Some SQLitePCLRaw bundle packages are no longer maintained [Tracking Issue #5108](https://github.com/dotnet/EntityFramework.Docs/issues/5108) ##### Old behavior -Previously, the `SQLitePCLRaw.bundle_e_sqlcipher` NuGet package provided encryption-enabled SQLite builds at no cost. +Previously, the `SQLitePCLRaw.bundle_e_sqlcipher`, `SQLitePCLRaw.bundle_sqlite3`, `SQLitePCLRaw.bundle_winsqlite3`, `SQLitePCLRaw.bundle_green`, and `SQLitePCLRaw.bundle_e_sqlite3mc` packages provided a convenient way to configure SQLitePCLRaw with the corresponding SQLite provider. ##### New behavior -Starting with SQLitePCLRaw 3.0 (used by Microsoft.Data.Sqlite 11.0), the `SQLitePCLRaw.bundle_e_sqlcipher` package has been deprecated and removed from NuGet. No-cost encryption-enabled SQLite builds are no longer distributed. +The `SQLitePCLRaw.bundle_e_sqlcipher`, `SQLitePCLRaw.bundle_sqlite3`, `SQLitePCLRaw.bundle_winsqlite3`, `SQLitePCLRaw.bundle_green`, and `SQLitePCLRaw.bundle_e_sqlite3mc` packages are no longer updated by the SQLitePCLRaw maintainer. They are not compatible with `SQLitePCLRaw.Core` 3.0 and later, so applications that directly reference any of these packages alongside `SQLitePCLRaw.Core` 3.x will encounter conflicts. Applications should migrate to the recommended alternatives to avoid future breakage. ##### Why -The previous no-cost `SQLitePCLRaw.bundle_e_sqlcipher` package was barely maintained, which is a significant concern for encryption software where security vulnerabilities may go unpatched. The SQLitePCLRaw maintainer removed these builds in version 3.0 in favor of professionally maintained, paid alternatives that provide ongoing security updates. +The SQLitePCLRaw maintainer removed these bundles in version 3.0; each bundle contained only a single line of configuration code and added unnecessary packaging overhead while the underlying provider packages continue to be supported. The `SQLitePCLRaw.bundle_e_sqlcipher` package is particularly affected: it provided encryption-enabled builds that are barely maintained, which is a security concern for encryption software where vulnerabilities may go unpatched. ##### Mitigations -If you need SQLite encryption, you have the following options: +**If using `SQLitePCLRaw.bundle_e_sqlcipher`** (encryption-enabled SQLite), migrate to one of the following alternatives: -- **SQLite3 Multiple Ciphers**: Starting with Microsoft.Data.Sqlite 11.0, the default SQLite build supports encryption and can be configured to use SQLCipher-compatible encryption. See [Microsoft.Data.Sqlite now bundles SQLite3 Multiple Ciphers](#sqlite3mc). NuGet packages are also available from [SQLite3MultipleCiphers-NuGet](https://github.com/utelle/SQLite3MultipleCiphers-NuGet). - - When encrypting a new database or opening an existing database that was encrypted with SQLCipher, you must configure the cipher scheme in the connection string using URI parameters—for example: `Data Source=file:example.db?cipher=sqlcipher&legacy=4;Password=`. See [How to open an existing database encrypted with SQLCipher](https://github.com/utelle/SQLite3MultipleCiphers-NuGet#how-to-open-an-existing-database-encrypted-with-sqlcipher) for details. -- **SQLite Encryption Extension (SEE)**: This is the official encryption implementation from the SQLite team. A paid license is required. See [https://sqlite.org/com/see.html](https://sqlite.org/com/see.html) for details. NuGet packages are available through [SourceGear's SQLite build service](https://github.com/ericsink/SQLitePCL.raw/wiki/SQLite-encryption-options-for-use-with-SQLitePCLRaw). -- **SQLCipher**: Purchase supported builds from [Zetetic](https://www.zetetic.net/sqlcipher/), or build the [open source code](https://github.com/sqlcipher/sqlcipher) yourself. - -For more details, see [SQLite encryption options for use with SQLitePCLRaw](https://github.com/ericsink/SQLitePCL.raw/wiki/SQLite-encryption-options-for-use-with-SQLitePCLRaw) and [SQLitePCLRaw 3.0 Release Notes](https://github.com/ericsink/SQLitePCL.raw/blob/main/v3.md). - - +- **SQLite3 Multiple Ciphers**: NuGet packages are available from [SQLite3MultipleCiphers-NuGet](https://github.com/utelle/SQLite3MultipleCiphers-NuGet). Reference `Microsoft.Data.Sqlite.Core` together with `SQLite3MC.PCLRaw.bundle`: -#### Some SQLitePCLRaw bundle packages have been removed + ```xml + + + ``` -[Tracking Issue #5108](https://github.com/dotnet/EntityFramework.Docs/issues/5108) - -##### Old behavior - -Previously, the `SQLitePCLRaw.bundle_sqlite3`, `SQLitePCLRaw.bundle_winsqlite3`, `SQLitePCLRaw.bundle_green`, and `SQLitePCLRaw.bundle_e_sqlite3mc` packages provided a convenient way to configure SQLitePCLRaw with the corresponding SQLite provider. - -##### New behavior - -Starting with SQLitePCLRaw 3.0 (used by Microsoft.Data.Sqlite 11.0), these bundle packages have been removed. If your application depended on one of these bundles, use one of the following migration paths. - -##### Why + When encrypting a new database or opening an existing database that was encrypted with SQLCipher, configure the cipher scheme using URI parameters—for example: `Data Source=file:example.db?cipher=sqlcipher&legacy=4`. See [How to open an existing database encrypted with SQLCipher](https://github.com/utelle/SQLite3MultipleCiphers-NuGet#how-to-open-an-existing-database-encrypted-with-sqlcipher) for details. -Each of these bundle packages contained only a single line of configuration code and added unnecessary packaging overhead. The corresponding provider packages are still supported. +- **SQLite Encryption Extension (SEE)**: The official encryption implementation from the SQLite team. A paid license is required. See [https://sqlite.org/com/see.html](https://sqlite.org/com/see.html) and [SourceGear's SQLite build service](https://github.com/ericsink/SQLitePCL.raw/wiki/SQLite-encryption-options-for-use-with-SQLitePCLRaw) for NuGet options. -##### Mitigations +- **SQLCipher**: Purchase supported builds from [Zetetic](https://www.zetetic.net/sqlcipher/), or build the [open source code](https://github.com/sqlcipher/sqlcipher) yourself. -**If using `bundle_sqlite3` or `bundle_winsqlite3`**, replace the removed bundle package with the corresponding provider package: +**If using `SQLitePCLRaw.bundle_sqlite3` or `SQLitePCLRaw.bundle_winsqlite3`**, replace the bundle package with the corresponding provider package: ```xml @@ -600,7 +585,7 @@ static void Init() } ``` -**If using `bundle_e_sqlite3mc`**, replace the package reference with `SQLite3MC.PCLRaw.bundle`: +**If using `SQLitePCLRaw.bundle_e_sqlite3mc`**, replace the package reference with `SQLite3MC.PCLRaw.bundle`: ```xml @@ -610,21 +595,19 @@ static void Init() ``` -**If using `bundle_green`**, the recommended migration path is to switch to `SQLitePCLRaw.bundle_e_sqlite3`. Alternatively, use `SQLitePCLRaw.config.e_sqlite3` paired with a separate native library package like `SourceGear.sqlite3`, which allows you to update the SQLite version independently: +**If using `SQLitePCLRaw.bundle_green`**, switch to `SQLitePCLRaw.bundle_e_sqlite3`. Alternatively, use `SQLitePCLRaw.config.e_sqlite3` paired with a separate native library package such as `SourceGear.sqlite3`, which allows updating the SQLite version independently: ```xml ``` -If you only target iOS and want to continue using the system SQLite library, reference the provider directly: +If you only target iOS and want to use the system SQLite library, reference the provider directly and initialize it explicitly: ```xml ``` -And initialize it explicitly: - ```csharp static void Init() { @@ -632,82 +615,30 @@ static void Init() } ``` -> [!NOTE] -> If you are using `SQLitePCLRaw.bundle_e_sqlite3`, no changes are required—just update the version number. See the [SQLitePCLRaw 3.0 Release Notes](https://github.com/ericsink/SQLitePCL.raw/blob/main/v3.md) for details. +For more details, see [SQLite encryption options for use with SQLitePCLRaw](https://github.com/ericsink/SQLitePCL.raw/wiki/SQLite-encryption-options-for-use-with-SQLitePCLRaw) and [SQLitePCLRaw 3.0 Release Notes](https://github.com/ericsink/SQLitePCL.raw/blob/main/v3.md). ### Low-impact changes - + -#### Microsoft.Data.Sqlite now bundles SQLite3 Multiple Ciphers +#### SQLite no longer supports UWP and classic Xamarin -[Tracking PR dotnet/efcore#38402](https://github.com/dotnet/efcore/pull/38402) +[Tracking Issue #5108](https://github.com/dotnet/EntityFramework.Docs/issues/5108) ##### Old behavior -The `Microsoft.Data.Sqlite` package referenced `SQLitePCLRaw.bundle_e_sqlite3`, which provides the standard `e_sqlite3` native SQLite build. This build has no encryption support, so setting a password (for example, via `SqliteConnectionStringBuilder.Password` or the `Password` connection-string keyword) failed at runtime. +Previously, `SQLitePCLRaw.bundle_e_sqlite3` included native SQLite builds for Universal Windows Platform (UWP) and classic Xamarin (Xamarin.iOS, Xamarin.Android, and Xamarin.Mac) targets. ##### New behavior -Starting with `Microsoft.Data.Sqlite` 11.0, the package references `SQLite3MC.PCLRaw.bundle`, which provides the `e_sqlite3mc` native build ([SQLite3 Multiple Ciphers](https://github.com/utelle/SQLite3MultipleCiphers)). This build receives updates on NuGet.org more promptly than `SQLitePCLRaw.bundle_e_sqlite3`. - -As an added bonus, encryption (including setting a password) now works out of the box. See the [SQLite3 Multiple Ciphers documentation](https://github.com/utelle/SQLite3MultipleCiphers-NuGet#passphrase-based-database-encryption-support) for details on enabling passphrase-based database encryption. - -This change also applies to the EF Core SQLite provider (`Microsoft.EntityFrameworkCore.Sqlite`), which references `SQLite3MC.PCLRaw.bundle` through `Microsoft.Data.Sqlite`. +Starting with `SQLitePCLRaw.bundle_e_sqlite3` 2.1.12 (referenced by `Microsoft.Data.Sqlite` 11.0), native builds for UWP and classic Xamarin are no longer included. Applications targeting these platforms can no longer use the bundled native SQLite library. ##### Why -The primary reason for the switch is maintenance and security: new versions of the `e_sqlite3` native build are no longer published to NuGet.org through `SQLitePCLRaw.bundle_e_sqlite3` in a timely manner, which means security fixes in upstream SQLite can be delayed. SQLite3 Multiple Ciphers is an actively maintained project that tracks upstream SQLite releases and ships updated builds promptly, so it was adopted as the default native build for `Microsoft.Data.Sqlite`. As an added bonus, it also supports encryption. This means it can replace the `SQLitePCLRaw.bundle_e_sqlcipher` package that was deprecated and removed (see [Encryption-enabled SQLite packages have been removed](#sqlite-encryption-removed)). +[SQLite 3.53.0](https://sqlite.org/releaselog/3_53_0.html) (shipped by `SQLitePCLRaw.bundle_e_sqlite3` 2.1.12) no longer supports UWP and classic Xamarin. The SQLitePCLRaw maintainer dropped these builds in order to keep up with newer upstream SQLite releases. ##### Mitigations -For most applications, **no action is required**. SQLite3 Multiple Ciphers is a superset of SQLite that behaves identically to the standard build for unencrypted databases—it only applies encryption when you explicitly supply a key or password. Existing unencrypted databases continue to open and work unchanged. - -Review the following cases, which may require action in some applications: - -- **Direct `SQLitePCLRaw.bundle_e_sqlite3` reference.** If your application directly references `SQLitePCLRaw.bundle_e_sqlite3`, it conflicts with the new `SQLite3MC.PCLRaw.bundle` dependency brought in by `Microsoft.Data.Sqlite` (or `Microsoft.EntityFrameworkCore.Sqlite`). Remove the direct `SQLitePCLRaw.bundle_e_sqlite3` reference unless you intentionally switch to the `.Core` packages shown below. - -- **Native library and provider name change.** The bundled native library is now `e_sqlite3mc` (rather than `e_sqlite3`), and the provider initialized by the bundle is `SQLite3Provider_e_sqlite3mc`. This matters if your application: - - References a specific native asset filename (for example, `e_sqlite3`) in publishing, trimming, AOT, or single-file configuration. Update those references to `e_sqlite3mc`. - -- **Platform (RID) coverage.** SQLite3 Multiple Ciphers doesn't currently include native binaries for every runtime identifier covered by `SourceGear.sqlite3`; for example, `linux-riscv64`, `linux-musl-riscv64`, and `linux-musl-s390x` aren't included. If you target a platform that the new bundle doesn't include, the native library may fail to load at runtime. In that case, revert to the standard build using the package references below. - -- **Linux glibc requirement and opt-out.** The bundled `e_sqlite3mc` library is prebuilt native code. On Linux, it currently requires glibc 2.33 or later; on older distributions, loading it can fail at runtime with an error such as `GLIBC_2.33 not found`. If the target system is unable to satisfy this requirement, follow the opt-out steps below. +Migrate UWP applications to the [Windows App SDK](/windows/apps/windows-app-sdk/) and classic Xamarin applications to [.NET MAUI](/dotnet/maui/), which are supported on modern .NET. -- **Reserved encryption keywords.** SQLite3 Multiple Ciphers reserves certain connection-string/URI parameters and PRAGMAs (such as `key`, `hexkey`, and `cipher`) for encryption configuration. This is unlikely to affect typical applications, but if you happened to use these names for unrelated purposes, behavior may differ. - -- **Double-quoted string literal support.** `e_sqlite3mc` doesn't include SQLite's legacy support for double-quoted string literals. If your SQL uses double quotes for string values, change it to use single quotes; double quotes should be used only for identifiers. Review raw SQL in your application (for example, SQL passed to `FromSql`, `ExecuteSql`, or migrations operations), and use SQL logging or integration tests to identify affected commands. - -If you want to keep using the standard, non-encrypted `e_sqlite3` build, reference `Microsoft.Data.Sqlite.Core` together with `SQLitePCLRaw.bundle_e_sqlite3` instead of the `Microsoft.Data.Sqlite` meta-package: - -```xml - - -``` - -For EF Core, reference `Microsoft.EntityFrameworkCore.Sqlite.Core` instead of `Microsoft.EntityFrameworkCore.Sqlite` and add the standard bundle: - -```xml - - -``` - -If you need to use a system-installed SQLite library instead of a bundled one, reference `Microsoft.Data.Sqlite.Core` together with `SQLitePCLRaw.provider.sqlite3` instead of the `Microsoft.Data.Sqlite` meta-package: - -```xml - - -``` - -For EF Core: - -```xml - - -``` - -And initialize the provider explicitly before using SQLite: - -```csharp -SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); -``` +If you must remain on UWP or classic Xamarin, stay on an earlier version of `SQLitePCLRaw.bundle_e_sqlite3` that still includes the native builds for these platforms. From 972e4efb6faed7ecf98bf60e8d5d66de653a7099 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 11:09:36 +0200 Subject: [PATCH 12/19] Document breaking change: Cosmos undefined projections now throw (EF Core 11) (#5433) --- .../core/providers/cosmos/querying.md | 45 ++++++++++++++ .../ef-core-11.0/breaking-changes.md | 60 +++++++++++++++++++ .../core/what-is-new/ef-core-11.0/whatsnew.md | 19 ++++++ 3 files changed, 124 insertions(+) diff --git a/entity-framework/core/providers/cosmos/querying.md b/entity-framework/core/providers/cosmos/querying.md index ccf7b92eee..3ca86a582a 100644 --- a/entity-framework/core/providers/cosmos/querying.md +++ b/entity-framework/core/providers/cosmos/querying.md @@ -213,6 +213,51 @@ Note that to filter out documents where a value is missing: + +```csharp +var results = await context.Entities + .Where(x => EF.Functions.IsDefined(x.Associate!.NestedAssociate!.Id)) + .Select(x => new { x.Associate!.NestedAssociate!.Id }) + .ToListAsync(); +``` + +Alternatively, use to substitute a default value for any property that could be `undefined`: + +```csharp +var results = await context.Entities + .Select(x => new { Id = EF.Functions.CoalesceUndefined(x.Associate!.NestedAssociate!.Id, Guid.Empty) }) + .ToListAsync(); +``` + +### Naked projections and SELECT VALUE + +A _naked projection_ — where a single value is projected directly without wrapping it in a DTO or anonymous type — is translated using `SELECT VALUE` in Cosmos DB SQL. As a result, any documents where the projected value is `undefined` are **silently skipped** and not included in the results: + +```csharp +// Naked projection - translated as SELECT VALUE, undefined results are silently omitted +var ids = await context.Entities + .Select(x => x.Associate!.NestedAssociate!.Id) + .ToListAsync(); +``` + +In contrast, any top-level instantiation in the projection (anonymous type, DTO, entity, or complex type) does **not** use `SELECT VALUE`. When a part of such a projection is `undefined`, an `InvalidOperationException` is thrown as described above. + +If silently skipping undefined results is not the desired behavior, wrap the projected value in an anonymous type or DTO to get a consistent error instead: + +```csharp +// Wrapped in an anonymous type - does not use SELECT VALUE, throws if undefined +var results = await context.Entities + .Select(x => new { x.Associate!.NestedAssociate!.Id }) + .ToListAsync(); +``` + ## Function mappings This section shows which .NET methods and members are translated into which SQL functions when querying with the Azure Cosmos DB provider. diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index f4e3c56230..ab8de1318f 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -23,6 +23,7 @@ This page documents API and behavior changes that have the potential to break ex |:--------------------------------------------------------------------------------------------------------------- | -----------| | [Sync I/O via the Azure Cosmos DB provider has been fully removed](#cosmos-nosync) | Medium | | [Microsoft.Data.SqlClient has been updated to 7.0](#sqlclient-7) | Medium | +| [Cosmos: exception thrown when a projection evaluates to undefined](#cosmos-undefined-projection) | Medium | | [Cosmos: illegal `id` characters are no longer escaped](#cosmos-no-id-escape) | Medium | | [SQL Server compatibility level now defaults to 160](#sqlserver-compatibility-level-160) | Low | | [EF Core now throws by default when no migrations are found](#migrations-not-found) | Low | @@ -126,6 +127,65 @@ If your application uses composite keys whose values can contain the characters - **Existing data**: Documents previously stored in Cosmos DB have `id` values using the old escape sequences (e.g. `Post|1|^2F`). After upgrading to EF Core 11, EF will generate unescaped `id` values (e.g. `Post|1|/`) and will no longer find those existing documents. To continue accessing existing data without migration, opt back into the old behavior using the `AppContext` switch described above—however, be aware that the id-collision bug will still be present. - **New data**: If you are creating a new application or database, avoid using these illegal characters in key values, as they are not valid in Cosmos DB resource `id` values. See the [Azure documentation](xref:Microsoft.Azure.Documents.Resource.Id) for details. + + +### Cosmos: exception thrown when a projection evaluates to undefined + +[Tracking Issue #34067](https://github.com/dotnet/efcore/issues/34067) + +#### Old behavior + +Previously, when projecting properties in anonymous type or DTO projections via navigation over optional relationships where a segment of the path was absent in the Cosmos DB document (causing the projected value to be `undefined`), the behavior was inconsistent: + +- With **single-property** anonymous type or DTO projections, EF translated the query using `SELECT VALUE`, which silently filtered out any documents where the projected value was `undefined`. This meant fewer results were returned than expected, with no indication of the missing data. +- With **multi-property** anonymous type or DTO projections, an `InvalidOperationException` with the message "Nullable object must have a value" was thrown. + +For example, given an entity `Entity` with an optional owned `Associate` which in turn has an optional owned `NestedAssociate`: + +```csharp +// Previously silently returned fewer results (undefined results were filtered out) +var singlePropResults = await context.Entities + .Select(x => new { x.Associate!.NestedAssociate!.Id }) + .ToListAsync(); + +// Previously threw InvalidOperationException: Nullable object must have a value +var multiPropResults = await context.Entities + .Select(x => new { x.Associate!.NestedAssociate!.Id, x.Associate!.NestedAssociate!.String }) + .ToListAsync(); +``` + +#### New behavior + +Starting with EF Core 11.0, an `InvalidOperationException` is thrown in both cases when any part of the projection evaluates to `undefined` in Azure Cosmos DB. The exception message is: + +> A part of the projection was undefined, use the coalesce operator to handle possible undefined values. + +#### Why + +The previous behavior was inconsistent. Single-property projections could silently discard results, making it easy to miss data without any indication of the problem. The new behavior ensures consistent, predictable error reporting whenever a projection encounters an undefined value. + +#### Mitigations + +Use to filter out documents where the projected value is missing: + +```csharp +var results = await context.Entities + .Where(x => EF.Functions.IsDefined(x.Associate!.NestedAssociate!.Id)) + .Select(x => new { x.Associate!.NestedAssociate!.Id }) + .ToListAsync(); +``` + +Alternatively, use to provide a default value for properties that could be `undefined`: + +```csharp +var results = await context.Entities + .Select(x => new + { + Id = EF.Functions.CoalesceUndefined(x.Associate!.NestedAssociate!.Id, Guid.Empty) + }) + .ToListAsync(); +``` + ## Low-impact changes diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index 8aef322ac0..210e20c29d 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -791,6 +791,25 @@ For more information, [see the documentation](xref:core/providers/cosmos/saving# This feature was contributed by [@JoasE](https://github.com/JoasE) - many thanks! + + +### Consistent behavior for undefined values in projections + +Previously, when projecting scalar properties via optional navigations where a document path was absent (resulting in an `undefined` value in Cosmos DB), behavior was inconsistent: single-property anonymous type projections silently dropped those results, while multi-property projections threw a cryptic exception. + +EF Core 11 now consistently throws an `InvalidOperationException` when any part of a projection evaluates to `undefined`. Use to filter or to provide fallbacks: + +```csharp +var results = await context.Entities + .Where(x => EF.Functions.IsDefined(x.Associate!.NestedAssociate!.Id)) + .Select(x => new { x.Associate!.NestedAssociate!.Id }) + .ToListAsync(); +``` + +For more information, see the [breaking changes documentation](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-undefined-projection). + +This feature was contributed by [@JoasE](https://github.com/JoasE) - many thanks! + ## Migrations From 5e7d3e3de1bac93dbb74aaace34ef273f9cdf1bc Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 11:10:01 +0200 Subject: [PATCH 13/19] Document -NoBuild switch for PMC Update-Database and Add-Migration (#5431) --- entity-framework/core/cli/powershell.md | 2 ++ .../core/what-is-new/ef-core-11.0/whatsnew.md | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/entity-framework/core/cli/powershell.md b/entity-framework/core/cli/powershell.md index 307c71e0a3..e254b3d9f1 100644 --- a/entity-framework/core/cli/powershell.md +++ b/entity-framework/core/cli/powershell.md @@ -124,6 +124,7 @@ Parameters: | `-Name ` | The name of the migration. This is a positional parameter and is required. | | `-OutputDir ` | The directory use to output the files. Paths are relative to the target project directory. Defaults to "Migrations". | | `-Namespace ` | The namespace to use for the generated classes. Defaults to generated from the output directory. | +| `-NoBuild` | Don't build the project before running the command. Intended to be used when the build is up-to-date. Added in EF Core 11. | The [common parameters](#common-parameters) are listed above. @@ -319,6 +320,7 @@ Updates the database to the last migration or to a specified migration. | `-Add` | Creates a new migration and applies it to the database in a single step. Uses Roslyn to compile the migration at runtime. When specified, a migration name is required and provides the name for the new migration. Added in EF Core 11. | | `-OutputDir ` | The directory to put migration files in. Paths are relative to the target project directory. Requires `-Add`. Added in EF Core 11. | | `-Namespace ` | The namespace to use for the generated migration classes. Requires `-Add`. Added in EF Core 11. | +| `-NoBuild` | Don't build the project before running the command. Intended to be used when the build is up-to-date. Added in EF Core 11. | The [common parameters](#common-parameters) are listed above. diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index 210e20c29d..e6f07095ed 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -918,6 +918,23 @@ Explicit command-line options always take precedence over configuration file val For more information, see [Configuration file](xref:core/cli/dotnet#configuration-file). + + +### `-NoBuild` for PMC migrations commands + +Starting with EF Core 11, the Package Manager Console `Add-Migration` and `Update-Database` commands support the `-NoBuild` switch, which skips the project build step before running the command. + +This is useful when a build succeeds but produces warnings that Visual Studio's Package Manager Console treats as errors (such as NuGet vulnerability warnings), which would otherwise block the commands from running: + +```powershell +Add-Migration MyMigration -NoBuild +Update-Database -NoBuild +``` + +Only use `-NoBuild` when the project is already up-to-date, since running with a stale build may produce unexpected results. + +For more information, see the [PMC tools reference](xref:core/cli/powershell). + ### Wildcard context support for migration commands From 6e876bb50bacc00983462cf63d75cf73e416b556 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 11:10:13 +0200 Subject: [PATCH 14/19] Document DbQueryConcurrencyException breaking change for split queries (EF Core 11) (#5430) --- .../ef-core-11.0/breaking-changes.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index ab8de1318f..c2da884b37 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -34,6 +34,7 @@ This page documents API and behavior changes that have the potential to break ex | [Cosmos: the default discriminator property is now named `Discriminator` in the model](#cosmos-discriminator-property-name) | Low | | [Owned JSON collections without an explicit key are obsolete](#owned-json-collections-obsolete) | Low | | [`Property` no longer configures primitive collections](#property-not-primitive-collection) | Low | +| [Split queries now throw when concurrent modifications are detected](#split-query-concurrency-exception) | Low | ## Medium-impact changes @@ -539,6 +540,74 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) In most cases no change is required, since primitive collections are discovered by convention. + + +### Split queries now throw when concurrent modifications are detected + +[Tracking Issue #33826](https://github.com/dotnet/efcore/issues/33826) + +#### Old behavior + +Previously, when a split query (using `AsSplitQuery()`) encountered out-of-order or orphaned child rows caused by concurrent data modifications between the split query's SQL statements, EF Core silently discarded the affected child collections. The result was an entity with an empty collection even though the related rows still existed—no exception was thrown and no warning was logged. + +#### New behavior + +Starting with EF Core 11.0, EF Core throws a `DbQueryConcurrencyException` when split query results cannot be correlated because of concurrent data modifications. The exception message describes the situation and suggests remediation: + +> The results of a split query could not be correlated because the data was modified concurrently while the query was executing. Re-execute the query, or execute it within a serializable or snapshot transaction to prevent concurrent modifications. + +#### Why + +Silently returning incorrect data (empty collections for entities that have related rows) is far worse than surfacing an error. This scenario is intrinsically caused by the lack of data-consistency guarantees in split queries when the database is modified between statements. Throwing a retriable exception makes the problem visible and gives callers a clear path to recovery. + +#### Mitigations + +The simplest mitigation is to re-execute the query; the concurrent modification is transient and the retry will typically succeed: + +```csharp +const int maxRetries = 3; + +List blogs; +for (var attempt = 0; attempt < maxRetries; attempt++) +{ + try + { + blogs = await context.Blogs + .Include(b => b.Posts) + .AsSplitQuery() + .ToListAsync(); + break; + } + catch (DbQueryConcurrencyException) when (attempt < maxRetries - 1) + { + // Retry on concurrent modification + } +} +``` + +Alternatively, wrap the split query in a serializable or snapshot transaction to prevent concurrent modifications from affecting the results: + +```csharp +await using var transaction = + await context.Database.BeginTransactionAsync(IsolationLevel.Serializable); + +var blogs = await context.Blogs + .Include(b => b.Posts) + .AsSplitQuery() + .ToListAsync(); + +await transaction.CommitAsync(); +``` + +If neither retry nor a transaction is acceptable, switch to a single query (`AsSingleQuery()`) which is always consistent: + +```csharp +var blogs = await context.Blogs + .Include(b => b.Posts) + .AsSingleQuery() + .ToListAsync(); +``` + ## Microsoft.Data.Sqlite breaking changes From a1725cedfccbcc21dfc0b8ff08e7d0d7678afd21 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 11:20:11 +0200 Subject: [PATCH 15/19] Document Cosmos JSON breaking changes for EF Core 11 (#5432) --- .../providers/cosmos/unstructured-data.md | 10 +- .../ef-core-11.0/breaking-changes.md | 99 +++++++++++++++++++ .../core/what-is-new/ef-core-11.0/whatsnew.md | 11 +++ 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/entity-framework/core/providers/cosmos/unstructured-data.md b/entity-framework/core/providers/cosmos/unstructured-data.md index e499aefb92..b122f3e9f9 100644 --- a/entity-framework/core/providers/cosmos/unstructured-data.md +++ b/entity-framework/core/providers/cosmos/unstructured-data.md @@ -11,7 +11,10 @@ EF Core was designed to make it easy to work with data that follows a schema def ## Accessing the raw JSON -It is possible to access the properties that are not tracked by EF Core through a special property in [shadow-state](xref:core/modeling/shadow-properties) named `"__jObject"` that contains a `JObject` representing the data received from the store and data that will be stored: +> [!NOTE] +> The `"__jObject"` shadow property was removed in EF Core 11. See [Breaking changes in EF Core 11](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-jObject-removed) for details. + +In EF Core 10 and earlier, it was possible to access properties not tracked by EF Core through a special property in [shadow-state](xref:core/modeling/shadow-properties) named `"__jObject"` that contained a `JObject` representing the data received from the store and data that will be stored: [!code-csharp[Unmapped](../../../../samples/core/Cosmos/UnstructuredData/Sample.cs?highlight=21,22&name=Unmapped)] @@ -35,10 +38,7 @@ It is possible to access the properties that are not tracked by EF Core through ``` > [!WARNING] -> The `"__jObject"` property is part of the EF Core infrastructure and should only be used as a last resort as it is likely to have different behavior in future releases. - -> [!NOTE] -> Changes to the entity will override the values stored in `"__jObject"` during `SaveChanges`. +> The `"__jObject"` property was part of the EF Core infrastructure. It exists only in EF Core 10 and earlier, and has been removed starting with EF Core 11. ## Using CosmosClient diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index c2da884b37..914953bdb9 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -21,6 +21,8 @@ This page documents API and behavior changes that have the potential to break ex | **Breaking change** | **Impact** | |:--------------------------------------------------------------------------------------------------------------- | -----------| +| [Cosmos: `__jObject` shadow property removed; JObject no longer used for serialization](#cosmos-jObject-removed) | Low | +| [Cosmos: Unmapped properties are no longer preserved](#cosmos-unmapped-properties) | High | | [Sync I/O via the Azure Cosmos DB provider has been fully removed](#cosmos-nosync) | Medium | | [Microsoft.Data.SqlClient has been updated to 7.0](#sqlclient-7) | Medium | | [Cosmos: exception thrown when a projection evaluates to undefined](#cosmos-undefined-projection) | Medium | @@ -32,10 +34,38 @@ This page documents API and behavior changes that have the potential to break ex | [SqlVector properties are no longer loaded by default](#sqlvector-not-auto-loaded) | Low | | [Cosmos: empty owned collections now return an empty collection instead of null](#cosmos-empty-collections) | Low | | [Cosmos: the default discriminator property is now named `Discriminator` in the model](#cosmos-discriminator-property-name) | Low | +| [Cosmos: floating-point values are now truncated when materializing to fixed-point types](#cosmos-truncation) | Low | | [Owned JSON collections without an explicit key are obsolete](#owned-json-collections-obsolete) | Low | | [`Property` no longer configures primitive collections](#property-not-primitive-collection) | Low | | [Split queries now throw when concurrent modifications are detected](#split-query-concurrency-exception) | Low | +## High-impact changes + + + +### Cosmos: Unmapped properties are no longer preserved + +[Tracking Issue #5421](https://github.com/dotnet/EntityFramework.Docs/issues/5421) + +#### Old behavior + +Previously, when EF Core read a Cosmos DB document that contained JSON properties not mapped in the EF model, those extra properties were preserved in the `__jObject` shadow property and written back to the database on the next `SaveChanges`. Unmapped data in documents was transparently round-tripped. + +#### New behavior + +Starting with EF Core 11, unmapped JSON properties in a Cosmos DB document are ignored when reading. Any extra properties that are not part of the EF model will be lost if the entity is subsequently saved. + +#### Why + +Because `__jObject` has been removed (see above), there is no mechanism to preserve unmapped properties. EF Core 11 uses a lean JSON reader that only processes the properties it knows about from the model. + +#### Mitigations + +If your application relies on preserving unmapped data, consider one of the following options: + +- **Use `CosmosClient` directly** for documents where you need full control over the JSON shape. +- **Map all relevant properties** explicitly in your EF model, including any extra fields that should be preserved. + ## Medium-impact changes @@ -189,6 +219,47 @@ var results = await context.Entities ## Low-impact changes + + +### Cosmos: `__jObject` shadow property removed; JObject no longer used for serialization + +[Tracking Issue #5421](https://github.com/dotnet/EntityFramework.Docs/issues/5421) + +#### Old behavior + +Previously, the Azure Cosmos DB provider added a shadow property named `"__jObject"` of type `JObject` (from `Newtonsoft.Json`) to every entity type. This property contained the raw JSON document as received from and sent to Cosmos DB, allowing access to unmapped or raw data: + +```csharp +var order = await context.Orders.FirstAsync(); +var rawJson = context.Entry(order).Property("__jObject").CurrentValue; +var billingAddress = rawJson["BillingAddress"]?.Value(); +``` + +EF Core used `Newtonsoft.Json` (via `JObject`) internally for all document serialization and deserialization. + +#### New behavior + +Starting with EF Core 11, the `__jObject` shadow property no longer exists. EF Core now uses `System.Text.Json` (`Utf8JsonReader`/`Utf8JsonWriter`) for document serialization and deserialization, and no longer depends on `Newtonsoft.Json`. + +Accessing the `"__jObject"` property will throw an `InvalidOperationException`. + +#### Why + +The `JObject`-based approach required a dependency on `Newtonsoft.Json` and limited performance improvements. Switching to `System.Text.Json` aligns EF Core Cosmos with the rest of the .NET ecosystem and enables significant performance gains in the materializer. + +#### Mitigations + +To access the raw JSON document, use the `CosmosClient` directly instead of relying on `__jObject`: + +```csharp +var cosmosClient = context.Database.GetCosmosClient(); +var container = cosmosClient.GetContainer("myDatabase", "myContainer"); +var response = await container.ReadItemAsync("1", new PartitionKey("1")); +var billingAddress = response.Resource.GetProperty("BillingAddress").GetString(); +``` + +For more information, see [Working with Unstructured Data in Azure Cosmos DB](xref:core/providers/cosmos/unstructured-data). + ### SQL Server compatibility level now defaults to 160 @@ -441,6 +512,34 @@ To restore the previous behavior where the discriminator property is also named modelBuilder.Entity().HasDiscriminator("$type"); ``` + + +### Cosmos: Floating-point values are now truncated when materializing to fixed-point types + +[Tracking Issue #38138](https://github.com/dotnet/efcore/issues/38138) + +#### Old behavior + +Previously, when a query projection returned a floating-point value (e.g., the result of a numeric expression such as `3 / 4` returned by Cosmos as `0.75`) and the target property was a fixed-point type (`int`, `long`, `decimal`, etc.), EF Core would **round** the value. For example, `0.75` would materialize as `1`. + +#### New behavior + +Starting with EF Core 11, such values are **truncated** instead of rounded. `0.75` now materializes as `0`, matching standard .NET integer truncation behavior (`(int)0.75 == 0`). + +#### Why + +Truncation is the standard .NET behavior for explicit numeric conversions and is consistent with how other providers behave. The previous rounding behavior was a bug. + +#### Mitigations + +If you relied on the previous rounding behavior, apply explicit rounding in your queries using `Math.Round`: + +```csharp +var result = await context.Products + .Select(p => (int)Math.Round((double)p.Int / (p.Int + 1))) + .SingleAsync(); +``` + ### Owned JSON collections without an explicit key are obsolete diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index e6f07095ed..519f80cbe6 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -791,6 +791,17 @@ For more information, [see the documentation](xref:core/providers/cosmos/saving# This feature was contributed by [@JoasE](https://github.com/JoasE) - many thanks! + + +### Modernized JSON serializer + +EF Core 11 modernizes the Azure Cosmos DB provider's document serialization and deserialization to use `System.Text.Json` (`Utf8JsonReader`/`Utf8JsonWriter`) internally, replacing the previous `Newtonsoft.Json`-based approach. This improves performance and removes the dependency on `Newtonsoft.Json`. + +As part of this change, the `__jObject` shadow property (of type `JObject`) that was previously added to every entity type has been removed, and unmapped JSON properties in documents are no longer preserved on round-trip. + +> [!IMPORTANT] +> These are breaking changes. See the [breaking changes documentation](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-jObject-removed) for details and mitigations. + ### Consistent behavior for undefined values in projections From 807ab1de564109632121bb468197bf8e0dab26b0 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Mon, 3 Aug 2026 14:04:38 -0700 Subject: [PATCH 16/19] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- entity-framework/core/cli/powershell.md | 2 +- .../core/what-is-new/ef-core-11.0/breaking-changes.md | 2 +- entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/entity-framework/core/cli/powershell.md b/entity-framework/core/cli/powershell.md index e254b3d9f1..8af08aaa12 100644 --- a/entity-framework/core/cli/powershell.md +++ b/entity-framework/core/cli/powershell.md @@ -122,7 +122,7 @@ Parameters: | Parameter | Description | |:-----------------------------------|:------------------------------------------------------------------------------------------------------------------------| | `-Name ` | The name of the migration. This is a positional parameter and is required. | -| `-OutputDir ` | The directory use to output the files. Paths are relative to the target project directory. Defaults to "Migrations". | +| `-OutputDir ` | The directory to use for the output files. Paths are relative to the target project directory. Defaults to "Migrations". | | `-Namespace ` | The namespace to use for the generated classes. Defaults to generated from the output directory. | | `-NoBuild` | Don't build the project before running the command. Intended to be used when the build is up-to-date. Added in EF Core 11. | diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 914953bdb9..699b2d23b3 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -57,7 +57,7 @@ Starting with EF Core 11, unmapped JSON properties in a Cosmos DB document are i #### Why -Because `__jObject` has been removed (see above), there is no mechanism to preserve unmapped properties. EF Core 11 uses a lean JSON reader that only processes the properties it knows about from the model. +Because `__jObject` has been removed (see [Cosmos: `__jObject` shadow property removed; JObject no longer used for serialization](#cosmos-jObject-removed)), there is no mechanism to preserve unmapped properties. EF Core 11 uses a lean JSON reader that only processes the properties it knows about from the model. #### Mitigations diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index 519f80cbe6..166688b531 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -791,7 +791,7 @@ For more information, [see the documentation](xref:core/providers/cosmos/saving# This feature was contributed by [@JoasE](https://github.com/JoasE) - many thanks! - + ### Modernized JSON serializer @@ -800,7 +800,7 @@ EF Core 11 modernizes the Azure Cosmos DB provider's document serialization and As part of this change, the `__jObject` shadow property (of type `JObject`) that was previously added to every entity type has been removed, and unmapped JSON properties in documents are no longer preserved on round-trip. > [!IMPORTANT] -> These are breaking changes. See the [breaking changes documentation](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-jObject-removed) for details and mitigations. +> These are breaking changes. See the [breaking changes documentation](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-jObject-removed) and [Cosmos: Unmapped properties are no longer preserved](xref:core/what-is-new/ef-core-11.0/breaking-changes#cosmos-unmapped-properties) for details and mitigations. From b59a698364e4260425cbc037ffe90831c2f47597 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Aug 2026 21:09:46 +0000 Subject: [PATCH 17/19] Order breaking change summary by impact Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../core/what-is-new/ef-core-11.0/breaking-changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 699b2d23b3..6646075789 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -21,12 +21,12 @@ This page documents API and behavior changes that have the potential to break ex | **Breaking change** | **Impact** | |:--------------------------------------------------------------------------------------------------------------- | -----------| -| [Cosmos: `__jObject` shadow property removed; JObject no longer used for serialization](#cosmos-jObject-removed) | Low | | [Cosmos: Unmapped properties are no longer preserved](#cosmos-unmapped-properties) | High | | [Sync I/O via the Azure Cosmos DB provider has been fully removed](#cosmos-nosync) | Medium | | [Microsoft.Data.SqlClient has been updated to 7.0](#sqlclient-7) | Medium | | [Cosmos: exception thrown when a projection evaluates to undefined](#cosmos-undefined-projection) | Medium | | [Cosmos: illegal `id` characters are no longer escaped](#cosmos-no-id-escape) | Medium | +| [Cosmos: `__jObject` shadow property removed; JObject no longer used for serialization](#cosmos-jObject-removed) | Low | | [SQL Server compatibility level now defaults to 160](#sqlserver-compatibility-level-160) | Low | | [EF Core now throws by default when no migrations are found](#migrations-not-found) | Low | | [`EFOptimizeContext` MSBuild property has been removed](#ef-optimize-context-removed) | Low | From 83d7b7bfd807ac4743eca7b5772e46d4729ad5cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Aug 2026 22:28:35 +0000 Subject: [PATCH 18/19] Update EF Core preview documentation metadata Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- entity-framework/core/cli/powershell.md | 2 +- entity-framework/core/providers/cosmos/querying.md | 2 +- entity-framework/core/providers/cosmos/unstructured-data.md | 2 +- .../core/what-is-new/ef-core-11.0/breaking-changes.md | 2 +- entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/entity-framework/core/cli/powershell.md b/entity-framework/core/cli/powershell.md index 8af08aaa12..7267c04a3d 100644 --- a/entity-framework/core/cli/powershell.md +++ b/entity-framework/core/cli/powershell.md @@ -2,7 +2,7 @@ title: EF Core tools reference (Package Manager Console) - EF Core description: Reference guide for the Entity Framework Core Visual Studio Package Manager Console author: SamMonoRT -ms.date: 11/08/2024 +ms.date: 08/03/2026 uid: core/cli/powershell ms.custom: sfi-ropc-nochange --- diff --git a/entity-framework/core/providers/cosmos/querying.md b/entity-framework/core/providers/cosmos/querying.md index 3ca86a582a..468c836b5e 100644 --- a/entity-framework/core/providers/cosmos/querying.md +++ b/entity-framework/core/providers/cosmos/querying.md @@ -2,7 +2,7 @@ title: Querying - Azure Cosmos DB Provider - EF Core description: Querying with the Azure Cosmos DB EF Core Provider author: SamMonoRT -ms.date: 09/19/2024 +ms.date: 08/03/2026 uid: core/providers/cosmos/querying --- # Querying with the EF Core Azure Cosmos DB Provider diff --git a/entity-framework/core/providers/cosmos/unstructured-data.md b/entity-framework/core/providers/cosmos/unstructured-data.md index b122f3e9f9..05bb5a64c1 100644 --- a/entity-framework/core/providers/cosmos/unstructured-data.md +++ b/entity-framework/core/providers/cosmos/unstructured-data.md @@ -2,7 +2,7 @@ title: Azure Cosmos DB Provider - Working with Unstructured Data - EF Core description: How to work with Azure Cosmos DB unstructured data using Entity Framework Core author: AndriySvyryd -ms.date: 11/05/2019 +ms.date: 08/03/2026 uid: core/providers/cosmos/unstructured-data --- # Working with Unstructured Data in EF Core Azure Cosmos DB Provider diff --git a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md index 6646075789..5e3ac81d9a 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/breaking-changes.md @@ -832,7 +832,7 @@ static void Init() If you only target iOS and want to use the system SQLite library, reference the provider directly and initialize it explicitly: ```xml - + ``` diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index 166688b531..a2b1a5114d 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -2,7 +2,7 @@ title: What's New in EF Core 11 description: Overview of new features in EF Core 11 author: SamMonoRT -ms.date: 06/10/2026 +ms.date: 08/03/2026 uid: core/what-is-new/ef-core-11.0/whatsnew --- From 79e194b8763f0dd13f1fd85da224b53491cb1fd4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:06:14 +0000 Subject: [PATCH 19/19] Document GroupBy query enhancements Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md index a2b1a5114d..1644d8c257 100644 --- a/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md +++ b/entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md @@ -220,6 +220,12 @@ Both optimizations can have a significant positive impact on query performance, More details on the benchmark are available [here](https://github.com/dotnet/efcore/issues/29182#issuecomment-4231140289), and as always, actual performance in your application will vary based on your schema, data and a variety of other factors. + + +### GroupBy enhancements + +EF Core 11 improves the translation and materialization of `GroupBy` queries. Queries can now compose navigation access and joins over a per-group top result, and aggregates over reference navigations are translated using joins before grouping rather than correlated subqueries. Left-joined non-entity projections, including anonymous types and DTOs, are also correctly materialized through joins and grouping. For more information, see [#38479](https://github.com/dotnet/efcore/pull/38479), [#38499](https://github.com/dotnet/efcore/pull/38499), [#38555](https://github.com/dotnet/efcore/pull/38555), [#38577](https://github.com/dotnet/efcore/pull/38577), [#38668](https://github.com/dotnet/efcore/pull/38668), and [#38687](https://github.com/dotnet/efcore/pull/38687). + ### Support for the new .NET 11 `FullJoin` operator