【问题标题】:Health Check using DBContext that is still being configured使用仍在配置的 DBContext 进行健康检查
【发布时间】:2022-01-06 18:58:09
【问题描述】:

我创建了一个调用注入服务的自定义运行状况检查,该服务使用 DbContext 来查询数据库以获取一些信息。当我启动我的应用程序时,我收到以下错误:

在配置时尝试使用上下文。一种 DbContext 实例不能在 OnConfiguring 内部使用,因为它是 此时仍在配置中。如果一秒钟就会发生这种情况 操作在前一个操作之前在此上下文中启动 完全的。不保证任何实例成员都是线程安全的。

有没有办法延迟健康检查,直到 DbContext 在启动时的某个地方注册?

下面是我的健康检查实现。

public class HealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken))
    {
        int userCount = dbService.GetUserCount();  // fails in the dbService here

        if (userCount > 0)
            return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));

        return Task.FromResult(new HealthCheckResult(context.Registration.FailureStatus, "An unhealthy result."));
    }
}

这是我的dbcontext通过AddDbContext注册后在启动时的注册方式

services.AddHealthChecks().AddCheck<HealthCheck>("user_health_check");

【问题讨论】:

  • 何时失败、应用程序加载或您何时请求健康检查端点?
  • 你是如何获得你的数据库上下文的?服务范围有吗?您是否有任何单例服务在不创建新范围的情况下获取上下文?
  • @SBI 两者兼有——健康检查端点在应用程序加载期间启动——全部在启动时的 ConfigureServices 方法中
  • @JeremyLakeman 是的,数据库上下文已注入。单例服务不支持。
  • 您还可以探索使用 MapWhen 来限制仅在请求时激活运行状况检查中间件。更多信息here.

标签: c# asp.net-core entity-framework-core health-check


【解决方案1】:

您可以通过添加带有自定义查询的DbContextCheck 来解决这个问题? (docs)

我的理解是你可以这样做:

services.AddHealthChecks()
        .AddDbContextCheck<YourDbContext>(customTestQuery:
            (db, cancel) => Task.FromResult(db.Users.Any()));

话虽如此,您可能在使用 DbContext 时遇到了并发问题。也许有一个async 调用不是awaited,或者你的上下文生命周期配置有问题。

在不知道如何注册和配置 dbcontext 或如何将其注入(或不注入)到看起来像存储库 (DbService.GetUserCount()) 的详细信息的情况下,我可以向您指出一些有关 avoiding DbContext threading issues 的其他文档和希望有用。

【讨论】:

  • 没有什么需要等待的,因为使用 dbcontext 的服务不是异步的。至于 AddDbContextCheck,它只是测试与 DB 的连接是否正常。
  • 至于并行 dbcontext 线程问题,我不认为这是因为 1) 我没有收到那种类型的多操作错误消息,2) 所有 DbContexts 都是 DI'd 3 ) 我收到更多“无法使用 DbContext,因为它仍在配置中”的错误
  • 您想要更多的东西有点奇怪。最佳实践是测试连接,最多执行一个快速返回的查询,例如select 1 * from dbo.Users,以证明您的应用可以连接并且可以查询。您希望通过探索您的存储库来检测到哪些变化?
  • 好吧,如果您可以使用查询来测试连接,那么为什么不使用 dbcontext 并且查询比选择 1 更具体一点呢?不应该是一样的吗?
  • 我建议的“解决方案”(实际上是变通)是使用您的 dbcontext 执行查询。它没有做的是使用您的存储库来完成它。我同意你的看法,你定义的探测似乎应该可以工作。您是否已证明您正在按预期(调试)将参数传递给探针?也许看看.AddTypeActivatedCheck(...)。我有点怀疑您在启动时会发生此错误。我不认为在启动时检查 exec 。它们应该与映射的端点及其选项一起运行。
猜你喜欢
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 2017-05-27
  • 2014-10-02
  • 2018-06-15
  • 2019-08-17
  • 2021-07-25
  • 1970-01-01
相关资源
最近更新 更多