DateTime.UtcNow由.net实体framework / postgresql自动转换为本地

kwvwclae  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(1)|浏览(111)

我使用DateTime.UtcNow在数据库中存储所有的DateTime作为UTC。它们以这种格式存储良好:2023-08-03 13:54:15.474570 +00:00但是,当我使用Linq命令从数据库中检索数据时,例如:await _context.SomeEntity.ToListAsync()。我正在获取本地格式的日期,如下所示:2023-08-03T15:54:15.47457+02:00是本地时间。
重要的是,当实体被更新时(除了日期时间之外的其他值),新的错误日期时间被存储回数据库中。
我使用以下版本:
.Net 7.0
Postgres软件包7.0.4

已尝试解决问题:

1-将所有属性从DateTime更改为DateTimeOffset。
2-将.UseNodaTime()应用于db选项,如下所示:options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"), x => x.UseNodaTime());的值。
3-在使用DateTime.SpecifyKind(dt, DateTimeKind.Utc)保存值之前指定类型。我想我必须在保存之前获取值,但这是一种不可能的解决方案,适用于我从数据库获取值的任何地方。

e5njpo68

e5njpo681#

您遇到了Entity Framework Core的问题,默认情况下,它将DateTime对象更改为系统的本地时间,除非指定为UTC。
您可以通过两种方式解决此问题:
1.覆盖DbContext中的SaveChanges:在DbContext中覆盖SaveChangesSaveChangesAsync方法允许您在保存所有DateTime对象之前手动将其转换为UTC。此方法可确保所有DateTime属性都以UTC保存。

public override int SaveChanges()
{
    UpdateDates();
    return base.SaveChanges();
}

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
    UpdateDates();
    return base.SaveChangesAsync(cancellationToken);
}

private void UpdateDates()
{
    var entities = ChangeTracker.Entries()
    .Where(e => e.Entity is SomeEntity && 
        (e.State == EntityState.Added || e.State == EntityState.Modified));

    foreach (var entity in entities)
    {
        if (entity.State == EntityState.Added)
        {
            ((SomeEntity)entity.Entity).CreationDate = DateTime.UtcNow;
        }

        ((SomeEntity)entity.Entity).ModificationDate = DateTime.UtcNow;
    }
}

字符串
1.在EF Core中使用值转换:使用值转换,您可以指定EF Core应如何在提供程序类型和.NET类型之间进行转换。这可以对所有实体的特定属性或所有DateTime属性执行。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        var dateTimeProperties = entityType.GetProperties()
            .Where(p => p.ClrType == typeof(DateTime) || p.ClrType == typeof(DateTime?));

        foreach (var property in dateTimeProperties)
        {
            modelBuilder.Entity(entityType.Name).Property(property.Name)
                .HasConversion(
                    v => v, 
                    v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
        }
    }
}


这两种方法都确保DateTime值被读取为UTC。如果处理不同时区的日期,可以考虑将它们存储为DateTimeOffset。

相关问题