EF Core and DateOnly

Solving some problems.

This isn’t going to be a long post. I just wanted to write this stuff down somewhere and this is as good of a place as any.

I’ve been using .NET 6 and EF Core 6 on a project for work. It’s been great so far, but I’ve wanted to use the new DateOnly type that was added in .NET 6 with EF Core. It seemed like a good fit to map to the date type in SQL. Unfortunately, this doesn’t really work out of the box. Here’s how I got it all working.

Configuring the Context

DateOnly doesn’t map to date by default. I’m sure EF 7 or later will fix this, but it requires a bit of configuring in EF Core 6. First you need a converter to convert DateOnly to and from DateTime. This is pretty simple:

DateOnlyConverter.cs
internal class DateOnlyConverter : ValueConverter<DateOnly, DateTime>
{
public DateOnlyConverter()
: base(d => d.ToDateTime(TimeOnly.MinValue),
d => DateOnly.FromDateTime(d))
{ }
}

Then you need to tell EF Core to both use that converter for DateOnly properties and to store those properties as date columns in the database. This, also, is not too complex. In your context class, the one that inherits from DbContext, override ConfigureConventions like so:

DataContext.cs
protected override void ConfigureConventions(ModelConfigurationBuilder builder)
{
// Store DateOnly values as 'date' columns
builder.Properties<DateOnly>()
.HaveConversion<DateOnlyConverter>()
.HaveColumnType("date");

// Any other "global" model configurations go here
}

After that, DateOnly properties work like you would expect. 🎉

Change Tracking

Of course, it works until it doesn’t. And this is what I ran into today that caused me to write this post.

EF Core has change tracking built in. It knows what entities are retrieved from the database and can tell when they have been modified so it can efficiently write them back to the database. It’s really good, except DateOnly properties don’t quite work with it.

Basically, if you have an entity with a DateOnly property, changing only the DateOnly property does not get noticed by the change tracker. Changing other properties at the same time as the DateOnly property will make it work fine, but sometimes that’s not what you need to do. This is very annoying but thankfully EF core has a way to manually let it know that an entity has changed:

_dbContext.Entry(entity).State = EntityState.Modified;

This frustrated me for an hour this morning, so I hope my 15 minute blog post can help someone else avoid the same frustration.

Photo by Sigmund on Unsplash.