代码之家  ›  专栏  ›  技术社区  ›  BlackMatrix

sqlite数据库中的EntityFramework核心格式DateTime

  •  6
  • BlackMatrix  · 技术社区  · 7 年前

    我将EF Core 2.0与SQLite一起使用,我希望在不丢失表列中人类可读的datetime值的情况下减少数据库的大小。当前,数据上下文将full DateTime CLR对象存储为字符串,如“2018-03-10 16:18:17.1013863”,但在我的情况下,“2018-03-10 16:18:17”就足够了。我该怎么办?

    3 回复  |  直到 7 年前
        1
  •  4
  •   bricelam    7 年前

    如果分数秒为零,则不存储分数秒。您可以安全地从现有数据中删除它们。更新应用程序以不指定它们。你可以热切地这样做(当你 DateTime 实体上的值)或在 SaveChanges

    public override int SaveChanges()
    {
        var dateTimeProperties =
            from e in ChangeTracker.Entries()
            where e.State == EntityState.Added
                    || e.State == EntityState.Modified
            from p in e.Properties
            where p.CurrentValue is DateTime
            select p;
        foreach (var property in dateTimeProperties)
        {
            // Strip millisecond
            var value = (DateTime)property.CurrentValue;
            property.CurrentValue = new DateTime(
                value.Year,
                value.Month,
                value.Day,
                value.Hour,
                value.Minute,
                value.Second);
        }
    
        return base.SaveChanges();
    }
    
        2
  •  2
  •   Desmond    4 年前

    添加bricelam回复。微调毫秒的更好(更短更快)代码是:

    property.CurrentValue = value.AddTicks(-value.Ticks % TimeSpan.TicksPerSecond)
    
        3
  •  0
  •   Desmond    5 年前

    如果您真的想减少更多的大小,可以为要减小大小的每个列添加自定义转换,如下所示:

     protected override void OnModelCreating(ModelBuilder constructor) =>
     constructor.Entity<YourEntity>().Property(c => c.DatePropertyOfYourEntity)
                        .HasConversion(f => f.ATextoYYMMDD(), s => s.AFechaYYMMDD());
    

    我使用了以下扩展方法来快速转换日期和字符串格式 YYMMDD :

        public static string ATextoYYMMDD(this DateTime fechaHora) {
    
            var chars = new char[6];
            var valor = fechaHora.Year % 100;
            chars[0] = (char)(valor / 10 + '0');
            chars[1] = (char)(valor % 10 + '0');
            valor = fechaHora.Month;
            chars[2] = (char)(valor / 10 + '0');
            chars[3] = (char)(valor % 10 + '0');
            valor = fechaHora.Day;
            chars[4] = (char)(valor / 10 + '0');
            chars[5] = (char)(valor % 10 + '0');
            return new string(chars);
    
        } 
    
        public static DateTime AFechaYYMMDD(this string s)
            => new DateTime((s[0] - '0') * 10 + s[1] - '0' + 2000, 
            (s[2] - '0') * 10 + s[3] - '0', (s[4] - '0') * 10 + s[5] - '0');
    

    如果要将其应用于实现接口的多个实体,可以执行以下操作:

                var convertidor = new ValueConverter<DateTime, string>
                    (f => f.ATextoYYMMDD(), s => s.AFechaYYMMDD());    
                foreach (var tipoEntidad in constructor.Model
                    .GetEntityTypes().Where(t => typeof(IYourInterface).IsAssignableFrom(t.ClrType.BaseType))) {
    
                    constructor.Entity(tipoEntidad.Name)
                        .Property("YourPropertyName").HasConversion(convertidor);
                }
    

    也可以将其应用于所有日期属性,请参见 EF CORE 2.1 HasConversion on all properties of type datetime