EF CORE 2.1 HasConversion on all properties of type datetime

I previously used DateTimeKindEntityMaterializerSource (Git) to convert all DateTime to UTC when reading entities because the default was unspecified.

With EF core 2.1 the DateTimeKindEntityMaterializerSource no longer works but we can actually do this

         builder
        .Entity<ESDataQuotation>()
        .Property(e => e.CreatedDate)
        .HasConversion(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc));

However, I have many properties of DateTime and I would like if there is a way to make the conversion for all property of type DateTime.


Excerpt from EF Core 2.1 Value Conversions documentation topic:

There is currently no way to specify in one place that every property of a given type must use the same value converter. This feature will be considered for a future release.

Until then, you can use the typical loop at the end of the OnModelCreating override where all entity types and properties are discovered:

var dateTimeConverter = new ValueConverter<DateTime, DateTime>(
    v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc));

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
    foreach (var property in entityType.GetProperties())
    {
        if (property.ClrType == typeof(DateTime) || property.ClrType == typeof(DateTime?))
            property.SetValueConverter(dateTimeConverter);
    }
}

Just thought I could throw in my two cents

There's an issue for that opened here: https://github.com/aspnet/EntityFrameworkCore/issues/10784

Ivan's solution will work for simple types like DateTime etc. but it will crash when using user-defined types when calling entityType.GetProperties() this is described better in the issue in the link above. To make it work with user-defined types you will have to use entityType.ClrType.GetProperties().

For universal workaround you can use this extension method:

public static class ModelBuilderExtensions
{
    public static ModelBuilder UseValueConverterForType<T>(this ModelBuilder modelBuilder, ValueConverter converter)
    {
        return modelBuilder.UseValueConverterForType(typeof(T), converter);
    }

    public static ModelBuilder UseValueConverterForType(this ModelBuilder modelBuilder, Type type, ValueConverter converter)
    {
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == type);
            foreach (var property in properties)
            {
                modelBuilder.Entity(entityType.Name).Property(property.Name)
                    .HasConversion(converter);
            }
        }

        return modelBuilder;
    }
}