diff --git a/src/Middleware/HealthChecks.EntityFrameworkCore/src/DbContextHealthCheck.cs b/src/Middleware/HealthChecks.EntityFrameworkCore/src/DbContextHealthCheck.cs index c4dd6c2602e6..64c2056991e7 100644 --- a/src/Middleware/HealthChecks.EntityFrameworkCore/src/DbContextHealthCheck.cs +++ b/src/Middleware/HealthChecks.EntityFrameworkCore/src/DbContextHealthCheck.cs @@ -8,9 +8,24 @@ namespace Microsoft.Extensions.Diagnostics.HealthChecks; internal sealed class DbContextHealthCheck : IHealthCheck where TContext : DbContext { - private static readonly Func> DefaultTestQuery = (dbContext, cancellationToken) => + private static readonly Func> DefaultTestQuery = async (dbContext, cancellationToken) => { - return dbContext.Database.CanConnectAsync(cancellationToken); + try + { + return await dbContext.Database.CanConnectAsync(cancellationToken); + } + catch (Exception exception) + { + // every exception returned by `CanConnectAsync` indicates cancellation, but we have to wrap every + // non-OperationCanceledException to make the check health message properly propagate, independent of the + // test query being used + if (exception is not OperationCanceledException) + { + throw new OperationCanceledException(null, exception, cancellationToken); + } + + throw; + } }; private readonly TContext _dbContext; @@ -41,7 +56,7 @@ public async Task CheckHealthAsync(HealthCheckContext context return new HealthCheckResult(context.Registration.FailureStatus); } - catch (Exception exception) + catch (Exception exception) when (exception is not OperationCanceledException || !cancellationToken.IsCancellationRequested) { return HealthCheckResult.Unhealthy(exception.Message, exception); }