EF Core and DateOnly

Solving some problems.

This isn鈥檛 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鈥檝e been using .NET 6 and EF Core 6 on a project for work. It鈥檚 been great so far, but I鈥檝e 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鈥檛 really work out of the box. Here鈥檚 how I got it all working.

Configuring the Context

DateOnly doesn鈥檛 map to date by default. I鈥檓 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:

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:

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鈥檛. 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鈥檚 really good, except DateOnly properties don鈥檛 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鈥檚 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.