Skip to content

Commit f87cdce

Browse files
committed
Breaking change note for DateOnly/TimeOnly scaffolding
Closes dotnet#4233
1 parent 222479a commit f87cdce

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,54 @@ uid: core/what-is-new/ef-core-8.0/breaking-changes
99
# Breaking changes in EF Core 8.0 (EF8)
1010

1111
This page will dcoument API and behavior changes that have the potential to break existing applications updating to EF Core 8.0.
12+
13+
## Summary
14+
15+
| **Breaking change** | **Impact** |
16+
|:---------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
17+
| [SQL Server `date` and `time` now scaffold to .NET `DateOnly` and `TimeOnly`](#sqlserver-date-time-only) | Medium |
18+
19+
## Medium-impact changes
20+
21+
<a name="sqlserver-date-time-only"></a>
22+
23+
### SQL Server `date` and `time` now scaffold to .NET `DateOnly` and `TimeOnly`
24+
25+
[Tracking Issue #24507](https://github.com/dotnet/efcore/issues/24507)
26+
27+
#### Old behavior
28+
29+
Previously, when scaffolding a SQL Server database with `date` or `time` columns, EF would generate entity properties with types [`DateTime`](https://learn.microsoft.com/dotnet/api/system.datetime) and [`TimeSpan`](https://learn.microsoft.com/dotnet/api/system.timespan).
30+
31+
#### New behavior
32+
33+
Starting with EF Core 8.0, `date` and `time` are scaffolded as [`DateOnly`](https://learn.microsoft.com/dotnet/api/system.dateonly) and [`TimeOnly`](https://learn.microsoft.com/dotnet/api/system.timeonly).
34+
35+
#### Why
36+
37+
`DateOnly` and `TimeOnly` were introduced in .NET 6.0, and are a perfect match for mapping the database date and time types. `DateTime` notably contains a time component that goes unused and can cause confusion when mapping it to `date`, and `TimeSpan` represents a time interval - possibly including days - rather than a time of day at which an event occurs. Using the new types prevents bugs and confusion, and provides clarity of intent.
38+
39+
#### Mitigations
40+
41+
This change only affects users which regularly re-scaffold their database into an EF code model ("database-first" flow).
42+
43+
It is recommended to react to this change by modifying your code to use the newly scaffolded `DateOnly` and `TimeOnly` types. However, if that isn't possible, you can edit the scaffolding templates to revert to the previous mapping. To do this, set up the templates as described on [this page](xref:core/managing-schemas/scaffolding/templates). Then, edit the `EntityType.t4` file, find where the entity properties get generated (search for `property.ClrType`), and change the code to the following:
44+
45+
```c#
46+
var clrType = property.GetColumnType() switch
47+
{
48+
"date" when property.ClrType == typeof(DateOnly) => typeof(DateTime),
49+
"date" when property.ClrType == typeof(DateOnly?) => typeof(DateTime?),
50+
"time" when property.ClrType == typeof(TimeOnly) => typeof(TimeSpan),
51+
"time" when property.ClrType == typeof(TimeOnly?) => typeof(TimeSpan?),
52+
_ => property.ClrType
53+
};
54+
55+
usings.AddRange(code.GetRequiredUsings(clrType));
56+
57+
var needsNullable = Options.UseNullableReferenceTypes && property.IsNullable && !clrType.IsValueType;
58+
var needsInitializer = Options.UseNullableReferenceTypes && !property.IsNullable && !clrType.IsValueType;
59+
#>
60+
public <#= code.Reference(clrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
61+
<#
62+
```

0 commit comments

Comments
 (0)