我以前使用DateTimeKindEntityMaterializerSource(Git)在读取实体时将所有DateTime转换为UTC,因为默认是未指定的。
使用EF核心2.1,DateTimeKindEntityMaterializerSource不再有效,但我们实际上可以这样做
builder
.Entity<ESDataQuotation>()
.Property(e => e.CreatedDate)
.HasConversion(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
但是,我有许多DateTime的属性,我想如果有一种方法可以为DateTime类型的所有属性进行转换。
摘自EF Core 2.1 Value Conversions文档主题:
目前无法在一个地方指定给定类型的每个属性必须使用相同的值转换器。此功能将在未来版本中考虑使用。
在此之前,您可以使用OnModelCreating
覆盖末尾的典型循环,其中发现了所有实体类型和属性:
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);
}
}
我以为我可以投入两分钱
这里有一个问题:https://github.com/aspnet/EntityFrameworkCore/issues/10784
Ivan的解决方案适用于DateTime
等简单类型,但在调用entityType.GetProperties()
时使用用户定义的类型时会崩溃,这在上面链接的问题中有更好的描述。要使其与用户定义的类型一起使用,您必须使用entityType.ClrType.GetProperties()
。
对于通用解决方法,您可以使用此扩展方法:
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;
}
}