sqlsugar与EFcore混用,对DateTime的处理出现了问题 返回

SqlSugar 沟通中
3 242
该叫什么 ck0077 发布于2周前
悬赏:0 飞吻

项目数据库为pgsql,项目中使用了TickerQ定时库,这个定时库必须使用pgsql的EFcore来读写数据。

<ItemGroup>
  <PackageReference Include="TickerQ" Version="10.3.0" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  </PackageReference>
  <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
  <PackageReference Include="TickerQ.EntityFrameworkCore" Version="10.3.0" />
</ItemGroup>


// 要使用ContextFactory来初始化表
public class TickerQDbContextFactory : IDesignTimeDbContextFactory<TickerQDbContext>
{
    public TickerQDbContext CreateDbContext(string[] args)
    {
        var options = new DbContextOptionsBuilder<TickerQDbContext>()
            .UseNpgsql(
                "Server=xxxxxx;Port=5432;Database=yyy;Uid=admin;Pwd=123456;",
                builder => builder.MigrationsAssembly("MyProjectName")
            )
            .Options;

        return new TickerQDbContext(options);

        // dotnet ef migrations add InitTickerQ --context TickerQDbContext
        // dotnet ef database update --context TickerQDbContext
    }
}

// 注入TickerQ
builder.Services.AddTickerQ(optionsBuilder =>
{
    // Core configuration
    optionsBuilder.ConfigureScheduler(schedulerOptions =>
    {
        schedulerOptions.MaxConcurrency = 5;
        schedulerOptions.NodeIdentifier = "bot-server";
        schedulerOptions.FallbackIntervalChecker = TimeSpan.FromSeconds(30);
    });

    // Configure the EF Core–backed operational store for TickerQ metadata, locks, and state.
    optionsBuilder.AddOperationalStore(efOptions =>
    {
        efOptions.UseTickerQDbContext<TickerQDbContext>(builder =>
        {
            builder.UseNpgsql(
                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                cfg => cfg.EnableRetryOnFailure(3, TimeSpan.FromSeconds(5), null)
            );
        });

        efOptions.SetDbContextPoolSize(5);
    });
});

// 使用TickerQ
app.UseTickerQ();


业务类定义大致如下

public class SysUserRole
{
    /// <summary>
    /// 用户Id
    /// </summary>
    public int UserId { get; set; }

    /// <summary>
    /// 角色名称
    /// </summary>
    public string RoleName { get; set; } = null!;

    /// <summary>
    /// 开始时间
    /// </summary>
    public DateTime StartTime { get; set; }

    /// <summary>
    /// 结束时间
    /// </summary>
    public DateTime EndTime { get; set; }
}


先不注入TickerQ,先使用sqlsugar插入一条数据

sugarClient.Insertable(new SysUserRole()
    {
        UserId = 1,
        RoleName = "test",
        StartTime = utcNow.Subtract(TimeSpan.FromMinutes(5)),
        EndTime = utcNow.AddMinutes(10),
    })
    .ExecuteCommand();


然后停掉项目,注入TickerQ,再在项目里执行查询

var utcNow = DateTime.UtcNow;
var alertTime = utcNow.AddMinutes(15); // 提前15分钟提醒


var userRoles = sugarClient.Queryable<SysUserRole>()
    // .Where(r => r.EndTime > utcNow && r.EndTime < alertTime)
    // .Where(r => r.EndTime < alertTime)
    .Where(r => r.EndTime > utcNow)
    .ToList();

发现无数据返回,打印sql后,检查sql语句没有问题(直接在datagrip中执行也没有问题,能查到数据)。
如果不注入TickerQ( 项目内没有UseNpgsql(....) ),则查询正常,有数据返回。

后面手动修改数据库记录,发现是数据库的EndTime的被当成了本地时间处理(减了8小时),再去与传入的utcNow进行比较,导致条件判断失败。
请问这种情况能怎么处理呢。数据类现在只能是DataTime,无法改成DataTimeOffset。


热忱回答3

  • 你看一下自定义类型。

    0 回复
  • 个别表可以用自定义类型处理,如果是所有表那就需要研究原因了。我不清楚你这个库的机质。

    0 回复
  • 找到了一个解决办法,就是在连接字符串的后面加上"Timezone=UTC",让pgsql把时间全部当成utc时间处理。
    我还得单独去引用一下EF core,看看是这个定时库的原因还是EF core自身的原因。

    0 回复