.NET Core 7 + Postgres:无法将timestamp with time zone转换为LocalDateTime
解决方案:PostgreSQL时区转换Linq查询报错(.NET7 + EF Core + NodaTime)
核心问题分析
升级到.NET7后,Npgsql EF Core Provider对NodaTime的映射逻辑发生了变化,同时你启用的Npgsql.EnableLegacyTimestampBehavior开关与UseNodaTime()配置冲突,导致时间类型转换失败。
步骤1:移除冲突的配置开关
删除启动项中的以下代码,启用NodaTime后无需保留传统时间戳行为,两者会导致类型映射冲突:
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
步骤2:修正实体属性类型
确保ClassOffering实体中,ClassStartTime和ClassEndTime的类型为**NodaTime.Instant?**(对应PostgreSQL的timestamptz类型),而非LocalDateTime或ZonedDateTime。这是timestamptz的标准NodaTime映射类型,能避免类型转换歧义。
步骤3:调整Linq查询中的时间转换写法
修改Linq选择器中的时间转换逻辑,确保EF Core能正确将其翻译为PostgreSQL的时区转换SQL:
model.PreviousClasses = await _context.ClassOfferingEnrollments.AsNoTracking() .Where(x => x.WorkerId == workerId && x.Offering != null && !x.ArchivedDate.HasValue && (x.Offering.ElectionId == null || x.Offering.Election.ElectionDate < currentDate)) .Select(x => new PreviousClassesViewModel() { ElectionName = x.Offering.Election.Name, LocationName = x.Offering.Location.Name, ClassOfferingType = x.Offering.Type, // 调整为可被EF Core翻译的时区转换写法 StartTime = x.Offering.ClassStartTime.Value.InZone(_currentCountyTimeZone).ToDateTimeUnspecified(), EndTime = x.Offering.ClassEndTime.Value.InZone(_currentCountyTimeZone).ToDateTimeUnspecified(), InstructorName = x.Offering.Instructor != null ? $"{x.Offering.Instructor.FirstName}_{x.Offering.Instructor.LastName}" : null }).ToListAsync();
可选:直接在查询中转换为字符串
如果ViewModel需要字符串格式的时间,可直接在Linq中转换(EF Core支持翻译NodaTime的ToString方法):
StartTime = x.Offering.ClassStartTime.Value.InZone(_currentCountyTimeZone).ToString("yyyy-MM-dd HH:mm:ss"), EndTime = x.Offering.ClassEndTime.Value.InZone(_currentCountyTimeZone).ToString("yyyy-MM-dd HH:mm:ss"),
步骤4:确保DbContext配置正确
若需要在OnConfiguring中配置NodaTime,需先引用对应的命名空间:
using Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime;
然后在OnConfiguring中添加:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(defaultConnectionString, o => o.UseNodaTime()); }
验证NuGet包版本
确保Npgsql.EntityFrameworkCore.PostgreSQL和Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime版本一致(当前均为7.0.3,符合要求),避免版本不兼容问题。
内容的提问来源于stack exchange,提问作者BrianLegg
相关产品推荐
相关产品推荐

