Skip to content

Commit 7e64f1f

Browse files
committed
Breaking change note for SQL Server json data type (#5085)
1 parent f1e0268 commit 7e64f1f

File tree

2 files changed

+92
-3
lines changed

2 files changed

+92
-3
lines changed

entity-framework/core/what-is-new/ef-core-10.0/breaking-changes.md

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,98 @@ This page documents API and behavior changes that have the potential to break ex
2020
> [!NOTE]
2121
> If you are using Microsoft.Data.Sqlite, please see the [separate section below on Microsoft.Data.Sqlite breaking changes](#MDS-breaking-changes).
2222
23-
| **Breaking change** | **Impact** |
24-
|:----------------------------------------------------------------------------------------------------------|------------|
25-
| [ExecuteUpdateAsync now accepts a regular, non-expression lambda](#ExecuteUpdateAsync-lambda) | Low |
23+
| **Breaking change** | **Impact** |
24+
|:--------------------------------------------------------------------------------------------------------------- | -----------|
25+
| [SQL Server json data type used by default on Azure SQL and compatibility level 170](#sqlserver-json-data-type) | Low |
26+
| [ExecuteUpdateAsync now accepts a regular, non-expression lambda](#ExecuteUpdateAsync-lambda) | Low |
2627

2728
## Low-impact changes
2829

30+
<a name="sqlserver-json-data-type"></a>
31+
32+
### SQL Server json data type used by default on Azure SQL and compatibility level 170
33+
34+
[Tracking Issue #36372](https://github.com/dotnet/efcore/issues/36372)
35+
36+
#### Old behavior
37+
38+
Previously, when mapping primitive collections or owned types to JSON in the database, the SQL Server provider stored the JSON data in an `nvarchar(max)` column:
39+
40+
```c#
41+
public class Blog
42+
{
43+
// ...
44+
45+
// Primitive collection, mapped to nvarchar(max) JSON column
46+
public string[] Tags { get; set; }
47+
// Owned entity type mapped to nvarchar(max) JSON column
48+
public List<Post> Posts { get; set; }
49+
}
50+
51+
protected override void OnModelCreating(ModelBuilder modelBuilder)
52+
{
53+
modelBuilder.Entity<Blog>().OwnsMany(b => b.Posts, b => b.ToJson());
54+
}
55+
```
56+
57+
For the above, EF previously generated the following table:
58+
59+
```sql
60+
CREATE TABLE [Blogs] (
61+
...
62+
[Tags] nvarchar(max),
63+
[Posts] nvarchar(max)
64+
);
65+
```
66+
67+
#### New behavior
68+
69+
With EF 10, if you configure EF with <xref:Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseAzureSql*> ([see documentation](xref:core/providers/sql-server/index#usage-and-configuration)), or configure EF with a compatibility level of 170 or above ([see documentation](xref:core/providers/sql-server/index#compatibility-level)), EF will map to the new JSON data type instead:
70+
71+
```sql
72+
CREATE TABLE [Blogs] (
73+
...
74+
[Tags] json
75+
[Posts] json
76+
);
77+
```
78+
79+
Note that if you have an existing table and are using <xref:Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseAzureSql*>, upgrading to EF 10 will cause a migration to be generated which alters all existing `nvarchar(max)` JSON columns to `json`. This alter operation is supported and should get applied seamlessly and without any issues, but is a non-trivial change to your database.
80+
81+
> [!NOTE]
82+
> For 10.0.0 rc1, support for the new JSON data type has been temporarily disabled for Azure SQL Database, due to lacking support. These issues are expected to be resolved by the time EF 10.0 is released, and the JSON data type will become the default until then.
83+
84+
#### Why
85+
86+
The new JSON data type introduced by SQL Server is a superior, 1st-class way to store and interact with JSON data in the database; it notably brings significant performance improvements ([see documentation](/sql/t-sql/data-types/json-data-type)). All applications using Azure SQL Database or SQL Server 2025 are encouraged to migrate to the new JSON data type.
87+
88+
#### Mitigations
89+
90+
If you do not wish to transition to the new JSON data type right away, you can configure EF with a compatibility level lower than 170:
91+
92+
```c#
93+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
94+
{
95+
optionsBuilder.UseSqlServer("<connection string>", o => o.UseCompatibilityLevel(160));
96+
}
97+
```
98+
99+
As an alternative, you can explicitly set the column type for your properties to be `nvarchar(max)`:
100+
101+
```c#
102+
public class Blog
103+
{
104+
public string[] Tags { get; set; }
105+
public List<Post> Posts { get; set; }
106+
}
107+
108+
protected override void OnModelCreating(ModelBuilder modelBuilder)
109+
{
110+
modelBuilder.Entity<Blog>().PrimitiveCollection(b => b.Tags).HasColumnType("nvarchar(max)");
111+
modelBuilder.Entity<Blog>().OwnsMany(b => b.Posts, b => b.ToJson().HasColumnType("nvarchar(max)"));
112+
}
113+
```
114+
29115
<a name="ExecuteUpdateAsync-lambda"></a>
30116

31117
### ExecuteUpdateAsync now accepts a regular, non-expression lambda

entity-framework/core/what-is-new/ef-core-10.0/whatsnew.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ WHERE JSON_VALUE([b].[Details], '$.Viewers' RETURNING int) > 3
118118

119119
Note that if your EF application already uses JSON via `nvarchar` columns, these columns will be automatically changed to `json` with the first migration. You can opt out of this by manually setting the column type to `nvarchar(max)`, or configuring a compatibility level lower than 170.
120120

121+
> [!NOTE]
122+
> For 10.0.0 rc1, support for the new JSON data type has been temporarily disabled for Azure SQL Database, due to lacking support. These issues are expected to be resolved by the time EF 10.0 is released, and the JSON data type will become the default until then.
123+
121124
<a name="default-constraint-names"></a>
122125

123126
### Custom default constraint names

0 commit comments

Comments
 (0)