EF CORE 2.1 HasConversion on all properties of type datetime

asp.net-core c# entity-framework-core

Question

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.

1
18
9/5/2018 11:56:15 AM

Accepted Answer

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);
    }
}
31
6/6/2018 7:58:27 PM

Popular Answer

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;
    }
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow