Что такое ServiceProviderOptions.ValidateScopes? Я чувствую, что не могу полностью понять, что он делает под капотом. Я наткнулся на это с учебником, но без объяснения.
Я предполагаю, что вы говорите об этом фрагменте кода:
services.BuildServiceProvider(new ServiceProviderOptions
{
ValidateScopes = true
});
// or
services.BuildServiceProvider(true); // or false
?
У поставщика ASP.NET Core есть механизм, который проверяет, разрешена ли служба с определенной областью одноэлементным контейнером. В ASP.NET Core есть два типа контейнеров. Основной одноэлементный контейнер, который действителен в течение всего времени существования приложения, и контейнеры с заданной областью для каждого запроса.
Этот параметр предотвратит разрешение служб с областью действия из одноэлементного контейнера, то есть, если вы случайно попытаетесь разрешить службу с областью действия в методе Configure
, вы получите исключение. А если вы его отключите, то не должны.
public void Configure(IApplicationBuilder app)
{
// will throw exception, since by default DbContext is registered as scope
app.ApplicationServices.GetRequiredService<MyDbContext>();
}
Исключение составляет нечто похожее на
InvalidOperationException: Cannot resolve 'IExampleService' from root provider because it requires scoped service 'MyDbContext'.
Такое поведение предназначено для предотвращения утечек памяти и разрешения служб с ограниченной областью действия (которые должны быть недолговечный) из одноэлементного контейнера, по сути, делая эти службы квази-синглетонами тоже (потому что они не будут удалены, пока контейнер не будет удален, а одноэлементный контейнер только удаляется при завершении работы приложения).
Правильный способ разрешить ограниченные службы внутри, например, метода Configure
, - это
// get scoped factory
var scopedFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
// create a scope
using (var scope = scopedFactory.CreateScope())
{
// then resolve the services and execute it
var context = scope.ServiceProvider.GetRequiredService<MyDbContext>();
}
// here, the child (scoped) container will be disposed and all scoped and transient services from it
Обновление 12/2020: Значение по умолчанию теперь false
для .NET 5.0..
~~ Значение по умолчанию - true
~~, и вы должны оставить его таким, если вы точно не знаете, что делаете, иначе вы рискуете неприятными утечками памяти (или объектами, уже удаленными исключениями) из-за невыпущенных служб.
Кроме того, я меняю его с Singletion на Scoped, надеясь, что, поскольку мой DbContext, по-видимому, имеет Scoped, Scoped внутри Scoped будет в порядке, и вместо этого я получаю эту ошибку: «Не удается разрешить службу с областью действия« ArithmosDaily.IHangfireJobSchedulerService »от корневого провайдера».
@RobertBurke: ValidatesScopes = true
- это значение по умолчанию ... Вы, вероятно, хотите, чтобы ValidateScopes = false
для запрещать этой проверки
@Tseng Извините, это была ошибка копирования / вставки. Я сделал установил значение false.
Извините, я переместил это к своему вопросу. Он немного больше, и указанное выше разрешение мне не помогло. Надеюсь, задав собственный вопрос, я получу ответ. Вышесказанное является скорее объяснением, но не практической реализацией, которая мне помогает. Спасибо хоть!
Кто-нибудь знает, в какой версии была добавлена эта функция ValidateScopes
?
@JimAho: Iirc 2.0. .NET Core 1.x просто разрешится из контейнера приложения без вашего внимания (что затрудняет отслеживание ошибок и утечек памяти)
как насчет переходного? stackoverflow.com/questions/57620528/…
У меня с этим небольшие проблемы. У меня похожая проблема. Я использую Hangfire, и он мне нужен для доступа к моей базе данных, чтобы обновлять ее некоторыми данными из API по расписанию. Я попытался установить
ValidatesScopes = true
в настройках службы в Startup, но это ничего не изменило в моем Configure: я все еще получаю сообщение об ошибке при настройке службы. Я понимаю, почему MS это сделала, но меня раздражает то, что они заставляют меня делать то, что, как я знаю, отлично работало в 1.1: например, у меня нет проблем с памятью и т. д.