From bdb0d5616aba86d84ecf932f59dd27f65ea3aa3f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Jul 2026 00:25:49 +0000 Subject: [PATCH 1/3] Document Cosmos JSON breaking changes Document https://github.com/dotnet/EntityFramework.Docs/issues/5421 --- .../providers/cosmos/unstructured-data.md | 10 +- .../ef-core-11.0/breaking-changes.md | 99 +++++++++++++++++++ .../core/what-is-new/ef-core-11.0/whatsnew.md | 13 +++ 3 files changed, 117 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..59060b8337 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 and has been removed in EF Core 11. It should not be used in any version of EF Core as it is no longer available. ## 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 f4e3c56230..1ef60a0452 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) | High | +| [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: illegal `id` characters are no longer escaped](#cosmos-no-id-escape) | Medium | @@ -31,9 +33,78 @@ 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 | +## High-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). + + + +### 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 @@ -380,6 +451,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 8aef322ac0..775b255497 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,19 @@ 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. + +This feature was contributed by [@JoasE](https://github.com/JoasE) - many thanks! + ## Migrations From 70a8ab092db791ac308b46110b01bc7435d328e1 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Tue, 28 Jul 2026 17:16:10 -0700 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- entity-framework/core/providers/cosmos/unstructured-data.md | 2 +- .../core/what-is-new/ef-core-11.0/breaking-changes.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/entity-framework/core/providers/cosmos/unstructured-data.md b/entity-framework/core/providers/cosmos/unstructured-data.md index 59060b8337..b122f3e9f9 100644 --- a/entity-framework/core/providers/cosmos/unstructured-data.md +++ b/entity-framework/core/providers/cosmos/unstructured-data.md @@ -38,7 +38,7 @@ In EF Core 10 and earlier, it was possible to access properties not tracked by E ``` > [!WARNING] -> The `"__jObject"` property was part of the EF Core infrastructure and has been removed in EF Core 11. It should not be used in any version of EF Core as it is no longer available. +> 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 1ef60a0452..7b245e5899 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 @@ -475,7 +475,7 @@ If you relied on the previous rounding behavior, apply explicit rounding in your ```csharp var result = await context.Products - .Select(p => (int)Math.Round((double)(p.Int / (p.Int + 1)))) + .Select(p => (int)Math.Round((double)p.Int / (p.Int + 1))) .SingleAsync(); ``` From 07f1855e2e55a8ac59852f0655a571195071ba15 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Jul 2026 00:18:49 +0000 Subject: [PATCH 3/3] Adjust Cosmos __jObject breaking change impact to low --- .../ef-core-11.0/breaking-changes.md | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 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 7b245e5899..57293842d6 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,7 +21,7 @@ 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) | High | +| [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 | @@ -39,47 +39,6 @@ This page documents API and behavior changes that have the potential to break ex ## High-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). - ### Cosmos: Unmapped properties are no longer preserved @@ -199,6 +158,47 @@ If your application uses composite keys whose values can contain the characters ## 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