---
title: "Native DateOnly and TimeOnly support in Entity Framework 8 in SQL Server"
description: ".NET 6 brought us two new datatypes: `DateOnly` and `TimeOnly`. For those types we don't have any first class support in Entity Framework - until now.\n\nThere is a recent change, that hit us with **Entity Framework 8** that might ease the situation and brings native support for those types."
updated: 2023-01-30
tags: ["Entity Framework", "EF 8", "C#", ".NET 8"]
canonical: "https://steven-giesel.com/blogPost/eae9904c-152f-4087-add9-ea78d1b15442/native-dateonly-and-timeonly-support-in-entity-framework-8-in-sql-server"
---

# Native DateOnly and TimeOnly support in Entity Framework 8 in SQL Server

.NET 6 brought us two new datatypes: `DateOnly` and `TimeOnly`. For those types we don't have any first class support in Entity Framework - until now.

There is a recent change, that hit us with **Entity Framework 8** that might ease the situation and brings native support for those types.

## `DateOnly` and `TimeOnly`

I guess those types are pretty self-explanatory. Until .NET 6, if you wanted to represent someone's birth**day** you had to include the time information as well, as this is just how `DateTime` works. But maybe the date part is enough for our use case. So `DateOnly` would be sufficient. And the good thing is, that `DateOnly` has no time zone information, which makes handling those kinds of information easier.

`TimeOnly` is the same but we instead of the date portion we take the time portion (independent of the date).
All in all `DateOnly` and `TimeOnly` are a nice way of decoupling this information from `DateTime`.

The problem with that **was** that those new types were not natively understandable/translateable by Entity Framework, especially with the SQL Server. 

## Mapping the types
To make this work, you had to define a custom (even though) simple converter or use a NuGet package, that did the same:
```csharp
public class DateOnlyConverter : ValueConverter<DateOnly, DateTime>
{
    public DateOnlyConverter() : base(
            dateOnly => dateOnly.ToDateTime(TimeOnly.MinValue),
            dateTime => DateOnly.FromDateTime(dateTime))
    {
    }
}

public class DateOnlyComparer : ValueComparer<DateOnly>
{
    public DateOnlyComparer() : base(
        (d1, d2) => d1.DayNumber == d2.DayNumber,
        d => d.GetHashCode())
    {
    }
}
```

That then can be used in your `DbContext`:
```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>(builder =>
    {
        builder.Property(x => x.Date)
            .HasConversion<DateOnlyConverter, DateOnlyComparer>();
    });
}
```

The same applies to `TimeOnly` respectively. And this seems odd given the fact that there are data types in SQL Serve that can represent that information perfectly.

## Entity Framework 8
There was a recent [Pull Request](https://github.com/dotnet/efcore/pull/30109) merged that enables you to use `DateOnly` and `TimeOnly` without any additional mapping logic. A small disclaimer here: The issue is flagged as "*consider-for-next-release*" which can indicate that this feature will not make it into Entity Framework 8, but I do think that it is very likely to land in the next release.

Just for the sake of completeness: Sqlite did already receive that functionality with .NET 6.

## Resources
 * GitHub: [Support the new BCL DateOnly and TimeOnly structs for SQL Server](https://github.com/dotnet/efcore/issues/24507)