【问题标题】:.NET6 and DateTime problem. Cannot write DateTime with Kind=UTC to PostgreSQL type 'timestamp without time zone'.NET6 和 DateTime 问题。无法将 Kind=UTC 的 DateTime 写入 PostgreSQL 类型“没有时区的时间戳”
【发布时间】:2023-04-11 12:40:01
【问题描述】:

我有一个常见的问题。

无法将 Kind=UTC 的 DateTime 写入 PostgreSQL 类型 'timestamp 没有时区'

我想启用 Legacy Timestamp 行为,如此处所述: https://github.com/npgsql/doc/blob/main/conceptual/Npgsql/types/datetime.md/

public MyDbContext(DbContextOptions<MyDbContext> contextOptions) : base(contextOptions)
        {
            AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
            AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
        }

但不起作用。我仍然遇到同样的错误。

我做错了什么。为什么遗留行为不起作用?

【问题讨论】:

标签: npgsql .net-6.0


【解决方案1】:

一个。添加解决

AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
StartupConfigure 方法。


B。或者,如果您根本没有 Startup 类,并且您的所有初始化都在带有主机构建器的 Program.cs 中,那么您的文件结尾可能如下所示:

... //adding services etc
var host = builder.Build();
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
... //your other scoped code
await host.RunAsync();

要使用System.Linq.Dynamic查询数据库,我们还需要指定时间类型。
过滤器示例: $"User.BirthDate&gt;={time.ToStringUtc()}"

public static string ToStringUtc(this DateTime time)
{
    return $"DateTime({time.Ticks}, DateTimeKind.Utc)";
}

同时,@istvan-kardkovacs 的回答 https://stackoverflow.com/a/70142836/7149454 也适用。基本上是为您正在创建的每个= new DateTime() 添加一个 .SetKindUtc()。在执行任何其他代码之前,在填充数据库的后台托管服务中,上面的开关显然对我不起作用。

【讨论】:

  • 当切换到 .net 6(从核心 3.1)我得到这个错误,这是解决它的最简单方法
【解决方案2】:

您必须为创建、插入、更新操作中的所有 DateTime 字段以及 Linq 查询中的 DateTime 比较设置 DateTimeKind。 我创建了一个小型扩展方法并添加到所有日期字段。

public static class DateTimeExtensions
{
    public static DateTime? SetKindUtc(this DateTime? dateTime)
    {
        if (dateTime.HasValue)
        {
            return dateTime.Value.SetKindUtc();
        }
        else
        {
            return null;
        }
    }
    public static DateTime SetKindUtc(this DateTime dateTime)
    {
        if (dateTime.Kind == DateTimeKind.Utc) { return dateTime; }
        return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
    }
}

【讨论】:

    【解决方案3】:

    我在我的DbContext 中添加了代码,以便在我的模型上的所有日期属性上进行设置:

    //dbcontext
    public override int SaveChanges()
    {
        _changeTrackerManager?.FixupEntities(this);
        return base.SaveChanges();
    }
    
    //don't forget the async method!
    public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
    {
        _changeTrackerManager?.FixupEntities(this);
        return base.SaveChangesAsync();
    }
    

    这个IChangeTrackerManager 依赖将被注入,然后任何时候实体被保存,它会调用下面的这个方法来修正所有的UTC日期时间类型。

    public void FixupEntities(DbContext context)
    {
        var dateProperties = context.Model.GetEntityTypes()
            .SelectMany(t => t.GetProperties())
            .Where(p => p.ClrType == typeof(DateTime))
            .Select(z => new
            {
                ParentName = z.DeclaringEntityType.Name,
                PropertyName = z.Name
            });
    
        var editedEntitiesInTheDbContextGraph = context.ChangeTracker.Entries()
            .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
            .Select(x => x.Entity);
    
        foreach (var entity in editedEntitiesInTheDbContextGraph)
        {
            var entityFields = dateProperties.Where(d => d.ParentName == entity.GetType().FullName);
    
            foreach (var property in entityFields)
            {
                var prop = entity.GetType().GetProperty(property.PropertyName);
    
                if (prop == null)
                    continue;
    
                var originalValue = prop.GetValue(entity) as DateTime?;
                if (originalValue == null)
                    continue;
    
                prop.SetValue(entity, DateTime.SpecifyKind(originalValue.Value, DateTimeKind.Utc));
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      当我的控制器反序列化对象并且我尝试使用 EF 和 Npgsql.EntityFrameworkCore.PostgreSQL 插入/更新它时,我也发生了同样的事情。我对所有日期都使用了 ToUniversalTime(),它对我有用。

      【讨论】:

        【解决方案5】:

        我找到了答案。不要将这些行添加到您的 dB 上下文中。而是在 WFP 应用程序中添加到 MainWindow.xaml.cs,如下所示:

        在前面添加“EnableLegacyTimestampBehavior”行 公共 MainWindow 方法中的 InitializeComponent 语句。

        您不需要“DisableDateTimeInfinityConversions”语句。

        您的带有 DateTime 的代码现在可以工作了。

        【讨论】:

          【解决方案6】:

          从@DLeh 稍微修改https://stackoverflow.com/a/71179214/507421

              private void ConvertDateTimesToUniversalTime()
              {
                  var modifiedEntites = ChangeTracker.Entries<IHaveAggregateRootId>()
                          .Where(e => (e.State == EntityState.Added || e.State == EntityState.Modified || e.State == EntityState.Deleted)).ToList();
                  foreach (var entry in modifiedEntites)
                  {
                      foreach (var prop in entry.Properties)
                      {
                          if (prop.Metadata.ClrType == typeof(DateTime))
                          {
                              prop.Metadata.FieldInfo.SetValue(entry.Entity, DateTime.SpecifyKind((DateTime)prop.CurrentValue, DateTimeKind.Utc));
                          }
                          else if (prop.Metadata.ClrType == typeof(DateTime?) && prop.CurrentValue != null)
                          {
                              prop.Metadata.FieldInfo.SetValue(entry.Entity, DateTime.SpecifyKind(((DateTime?)prop.CurrentValue).Value, DateTimeKind.Utc));
                          }
                      }
                  }
              }
          

          【讨论】:

            【解决方案7】:

            就我而言,这是我犯的一个错误

            InvitedOn = DateTime.Now
            

            应该是

            InvitedOn = DateTime.UtcNow
            

            成功了

            【讨论】:

              猜你喜欢
              • 2014-01-25
              • 1970-01-01
              • 2016-10-11
              • 2016-07-22
              • 2016-10-21
              • 2013-09-12
              • 1970-01-01
              • 2018-05-04
              • 2014-03-19
              相关资源
              最近更新 更多