提问人:Aamer 提问时间:8/3/2023 更新时间:8/4/2023 访问量:434
DateTime.UtcNow 由 .net entity framework / postgresql 自动转换为本地
DateTime.UtcNow is auto converted to local by .net entity framework / postgresql
问:
我使用将所有 DateTimes 作为 UTC 存储在数据库中。它们以这种格式存储得很好: 但是,当我使用 Linq 命令从数据库中检索数据时,例如:.
我以这样的本地格式获取日期:这是我的当地时间。DateTime.UtcNow
2023-08-03 13:54:15.474570 +00:00
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)
答:
您遇到 Entity Framework Core 问题,默认情况下,除非指定为 UTC,否则它会将 DateTime 对象更改为系统的本地时间。
您可以通过两种方式解决此问题:
- 重写 DbContext 中的 SaveChanges:重写 DbContext 中的方法允许您在保存所有 DateTime 对象之前手动将其转换为 UTC。此方法可确保所有 DateTime 属性都保存在 UTC 中。
SaveChanges
SaveChangesAsync
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;
}
}
- 在 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。
评论
timestamp [ (p) ] with time zone
select '2023-08-03 13:54:15.474570 +00:00'::timestamp; 2023-08-03 13:54:15.47457