EFcore 解决 SQLite 没有datetime 类型的问题
SQLite不支持EFcore 的DateTime类型,请参阅
SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations
解决办法
DatabaseContext.cs
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
if (Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite")
{
// SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations
// here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations
// To work around this, when the Sqlite database provider is used, all model properties of type DateTimeOffset
// use the DateTimeOffsetToBinaryConverter
// Based on: https://github.com/aspnet/EntityFrameworkCore/issues/10784#issuecomment-415769754
// This only supports millisecond precision, but should be sufficient for most use cases.
foreach (var entityType in builder.Model.GetEntityTypes())
{
var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTime)
|| p.PropertyType == typeof(DateTime?));
foreach (var property in properties)
{
builder
.Entity(entityType.Name)
.Property(property.Name)
.HasConversion(new DateTimeToTimeStampConverter());
}
}
}
}
DateTimeToTimeStampConverter
public class DateTimeToTimeStampConverter : ValueConverter<DateTime, long>
{
public DateTimeToTimeStampConverter(ConverterMappingHints mappingHints = null)
: base(
v => (long)TimeStampHelper.ConvertJavaTimeStamp(v),
v => TimeStampHelper.JavaTimeStampToDateTime(v),
mappingHints)
{
}
}
TimeStampHelper
public class TimeStampHelper
{
public static double ConvertUnixTimeStamp(DateTime time)
{
//create Timespan by subtracting the value provided from
//the Unix Epoch
TimeSpan span = (time - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime());
//return the total seconds (which is a UNIX timestamp)
return (double)span.TotalSeconds;
}
public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
}
public static double ConvertJavaTimeStamp(DateTime time)
{
//create Timespan by subtracting the value provided from
//the Unix Epoch
TimeSpan span = (time - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime());
//return the total Milliseconds (which is a Java timestamp)
return (double)span.TotalMilliseconds;
}
public static DateTime JavaTimeStampToDateTime(double javaTimeStamp)
{
// Java timestamp is milliseconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();
return dtDateTime;
}
}
问题解决!
参考
https://github.com/dotnet/efcore/issues/9071
https://gist.github.com/GeorgDangl/b90370124720ed8fed9539509aafd155#file-datetimeoffsetticksubtraction-cs
https://github.com/dotnet/efcore/tree/main/src/EFCore/Storage/ValueConversion