Los Morales
Los Morales

Reputation: 2155

Health Check using DBContext that is still being configured

I created a custom Health Check that calls an injected service, and that service uses a DbContext to query the DB to get some info. When I launched my application I get the following error:

An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside OnConfiguring since it is still being configured at this point. This can happen if a second operation is started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

Is there a way to delay the health check until the DbContext is registered somewhere in the startup?

Below is my health check implementation.

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."));
    }
}

This is how it is registered in the startup after my dbcontext is registered via AddDbContext

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

Upvotes: 1

Views: 4781

Answers (1)

Josh Gust
Josh Gust

Reputation: 4445

You may be able to get around this by adding a DbContextCheck with a custom query? (docs)

My understanding is that you can do something like this:

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

With that said, you may have a concurrency problem here with how your DbContext is being used. Perhaps there's an async call being made that isn't awaited, or maybe there's something wrong with how your context lifetime is configured.

Without knowing the details of how you're registering and configuring your dbcontext or how it's being injected (or not) into what looks like a repository (DbService.GetUserCount()) I can point you toward some additional documentation about avoiding DbContext threading issues and hope it is useful.

Upvotes: 2

Related Questions