#c# #asp.net-core #entity-framework-core #health-check
#c# #asp.net-core #entity-framework-core #проверка работоспособности
Вопрос:
Я создал пользовательскую проверку работоспособности, которая вызывает внедренную службу, и эта служба использует 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");
Комментарии:
1. Когда происходит сбой, загрузка приложения или когда вы запрашиваете конечную точку проверки работоспособности?
2. Как вы получаете свой контекст БД? Ограничена ли область действия службы? Есть ли у вас какие-либо одноэлементные службы, получающие контекст без создания новой области?
3. @SBI действительно оба — конечная точка проверки работоспособности запускается во время загрузки приложения — все в методе ConfigureServices при запуске
4. @JeremyLakeman Да, вводится контекст БД. Нет в одноэлементных службах.
5. Вы также можете изучить возможность использования MapWhen, чтобы ограничить активацию промежуточных программ проверки работоспособности только по запросу. Дополнительная информация здесь .
Ответ №1:
Возможно, вы сможете обойти это, добавив a DbContextCheck
с пользовательским запросом? (документы)
Насколько я понимаю, вы можете сделать что-то вроде этого:
services.AddHealthChecks()
.AddDbContextCheck<YourDbContext>(customTestQuery:
(db, cancel) => Task.FromResult(db.Users.Any()));
С учетом сказанного, у вас может возникнуть проблема параллелизма с тем, как используется ваш DbContext. Возможно, async
выполняется вызов, который не await
редактируется, или, может быть, что-то не так с настройкой времени жизни вашего контекста.
Не зная подробностей о том, как вы регистрируете и настраиваете свой dbcontext или как он вводится (или нет) в то, что выглядит как репозиторий ( DbService.GetUserCount()
) Я могу указать вам на некоторую дополнительную документацию об избежании проблем с потоками DbContext и надеюсь, что это полезно.
Комментарии:
1. Ожидать нечего, поскольку служба, использующая dbcontext, не является асинхронной. Что касается проверки AddDbContextCheck, это просто проверка, в порядке ли подключение к БД.
2. Что касается проблем с параллельными потоками dbcontext, я не думаю, что это происходит, поскольку 1) Я не получаю сообщение об ошибке такого типа с несколькими операциями, 2) все DbContexts являются DI’d 3) Я получаю больше сообщений об ошибке «невозможно использовать DbContext, поскольку он все еще настраивается»
3. Немного странно, что вам нужно что-то большее, чем это. Лучше всего протестировать соединение и, самое большее, выполнить быстрый возвращаемый запрос, например,
select 1 * from dbo.Users
чтобы доказать, что ваше приложение может подключаться и может запрашивать. Какие изменения вы надеетесь обнаружить, просматривая свой репозиторий?4. Что ж, если вы можете протестировать соединение с помощью запроса, то почему бы не использовать dbcontext, а запрос немного более конкретный, чем select 1? Разве это не должно работать так же?
5. «Решение» (обходной путь, на самом деле) Я предложил использовать ваш dbcontext для выполнения запроса. Чего он не делает, так это использует для этого ваш репозиторий. Я согласен с вами, определенный вами тест, похоже, должен работать. Вы доказали, что получаете аргументы для проверки, как и ожидалось (отладка)? Может быть, посмотрите
.AddTypeActivatedCheck(...)
. Я немного подозреваю, что эта ошибка возникает у вас при запуске. Я не думаю, что проверяет exec при запуске. Предполагается, что они должны выполняться совместно с отображенной конечной точкой и ее параметрами.