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:
internal class DateOnlyConverter : ValueConverter<DateOnly, DateTime>
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
ConfigureConventions like so:
protected override void ConfigureConventions(ModelConfigurationBuilder builder)
DateOnly properties work like you would expect. 🎉
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.