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 f4e3c56230..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,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: illegal `id` characters are no longer escaped](#cosmos-no-id-escape) | Medium | @@ -31,9 +33,37 @@ 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: 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 @@ -128,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 @@ -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