.Net Core 7 with Postgres 无法将带时区的数据库类型时间戳转换为 LocalDateTime

问题描述 投票:0回答:1

我读过一些与此非常相似的帖子,但我还没有找到答案。

我想要做的是从数据库中获取时间戳,将其转换为用户时区,然后将其转换为字符串——最好是在 EF Linq 语句中。

这是一个较小的 Linq 语句示例,但对我来说失败了。

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,
                    StartTime = x.Offering.ClassStartTime.Value.InZone(_currentCountyTimeZone).LocalDateTime,
                    EndTime = x.Offering.ClassEndTime.Value.InZone(_currentCountyTimeZone).LocalDateTime,
                    InstructorName = x.Offering.Instructor != null
                        ? x.Offering.Instructor.FirstName + "_" + x.Offering.Instructor.LastName
                        : null
                }).ToListAsync();

失败的部分是 InZone(_currentCountyTimeZone) 行。我也试过这个:

x.Offering.ClassStartTime.Value.InZone(DateTimeZoneProviders.Tzdb["America/New_York"]).LocalDateTime

我还读到 InZone 有一些问题,所以我也在另一篇文章中尝试了这个:

x.Offering.ClassStartTime.Value.InUtc().LocalDateTime

所有这些查询都给出相同的异常:

{"Can't cast database type timestamp with time zone to LocalDateTime"}

我已经阅读了其他几篇文章,所以我也设置了一些其他的东西。我的创业公司有这些:

AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

services.AddEntityFrameworkNpgsql()
                .AddDbContext<ElectionWorkerPortalContext>(options => options.UseNpgsql(defaultConnectionString, o => o.UseNodaTime()))

我还尝试通过以下方式在我的构建器上设置它:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder.UseNpgsql(o => o.UseNodaTime());

但是 UseNodaTime() 不作为该对象上的方法存在。

我已经通过 Nuget 安装了以下内容:

  <ItemGroup>
    <PackageReference Include="AWSSDK.S3" Version="3.7.103.1" />
    <PackageReference Include="AWSSDK.SecretsManager" Version="3.7.101.21" />
    <PackageReference Include="CsvHelper" Version="12.1.2" />
    <PackageReference Include="DataTables.AspNet.AspNetCore" Version="2.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="7.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
    <PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.3.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.3" />
    <PackageReference Include="Mindscape.Raygun4Net.AspNetCore" Version="6.6.6" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
    <PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.0.1" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="7.0.3" />
    <PackageReference Include="Rotativa.AspNetCore" Version="1.2.0" />
    <PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
    <PackageReference Include="Serilog.Enrichers.Process" Version="2.0.2" />
    <PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
    <PackageReference Include="Serilog.Formatting.Compact" Version="1.1.0" />
    <PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
    <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
    <PackageReference Include="System.Drawing.Common" Version="7.0.0" />
  </ItemGroup>

我认为这些就是所有的细节。如果有必要,我不介意安装另一个包,我唯一不愿意做的就是降级 .Net。我应该注意,在此升级之前我使用的是核心 3.1,一切正常。我是一位经验丰富的开发人员,但远非时区专家(它很复杂),因此欢迎任何帮助!我相信我目前拥有最新的一切,我只是想再次让它稳定下来。谢谢!

c# postgresql entity-framework .net-core nodatime
1个回答
0
投票

我最终创建了一个似乎可以完成这项工作的扩展方法。而不是打电话:

.InZone(_currentTimeZone)

其中 _currentTimeZone 是 DateTimeZone。我现在这样称呼我的分机:

.InZoneExtension(_currentTimeZone)

现在 _currentTimeZone 是一个字符串,我这样使用它:

public static ZonedDateTime InZoneExtension(this Instant instant, string timezone)
        {
            DateTimeZone zone = DateTimeZoneProviders.Tzdb[timezone];

            return instant.InZone(zone);
        }

希望这对某人有帮助。如果有人知道更好的解决方案,我仍然很想知道。

© www.soinside.com 2019 - 2024. All rights reserved.