.NET Core Scoped вызывается в синглтоне через DI - PullRequest
0 голосов
/ 16 мая 2018

Я получаю сообщение об ошибке в 2.0, которое я не использовал в .Net Core 1.1.

Cannot consume scoped service 'ArithmosDaily.Data.ArithmosContext' from singleton 'ArithmosDaily.IHangfireJobSchedulerService'.

Я использую Hangfire, и он мне нужен для доступа к моей базе данных (поэтому я внедряю свой контекст через DI), чтобы обновить базу данных некоторыми данными из API по расписанию. Таким образом, создается впечатление, что DbContext создается как Scoped, а я настраиваю свой сервис Hangfire как Singleton. В Core 1.1 не было никакой проверки для Scoped, вложенного в Singleton. Я знаю, что эта концепция работает, потому что я вырвал ее из другого проекта в проекте Core 1.1, и вложение Context в мой сервис Singleton работает нормально. (Меня раздражает, что Microsoft чувствует необходимость контролировать меня только потому, что я могу сделать что-то плохое).

Итак, я изменяю свой сервис Hangfire с Singleton на Scoped, надеясь, что мой DbContext, по-видимому, Scoped, что Scoped внутри Scoped будет в порядке, и вместо этого я получаю эту ошибку: Cannot resolve scoped service 'ArithmosDaily.IHangfireJobSchedulerService' from root provider. Я до сих пор не понимаю, что это означает. .

После небольшой копки я наткнулся на две ссылки внизу своего поста (и пока это все, что я могу найти). Я попытался установить services.BuildServiceProvider(false); в моем автозагрузке, как предлагалось в первой ссылке, но это ничего не изменило в моей конфигурации: я все еще получаю сообщение об ошибке при настройке моей службы.

Я полностью в замешательстве и не уверен, что еще можно попробовать. Может у меня код не в том месте? Я не уверен.

Вот мой код для запуска и настройки:

public void ConfigureServices(IServiceCollection services)
{
    services.BuildServiceProvider(false);

    string conn = Configuration.GetConnectionString("Arithmos");
    services.AddDbContext<ArithmosContext>(options => options.UseSqlite(conn));

    services.AddMvc();

    services.AddHangfire(x => x.UseSQLiteStorage(conn));
    services.AddScoped<IHangfireJobSchedulerService, HangfireJobSchedulerService>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
    lifetime.ApplicationStarted.Register(OnStartup);
    lifetime.ApplicationStopping.Register(OnShutdown);

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
        app.UseExceptionHandler("/Error");

    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });

    app.UseHangfireServer();
    app.UseHangfireDashboard(options: new DashboardOptions
    {
        Authorization = new[] { new HangfireAuthorizationFilter() }
    });
    jobSchedulerService = app.ApplicationServices.GetRequiredService<IHangfireJobSchedulerService>();
}

Я сталкивался с этими вопросами, но они мне не сильно помогли:

ASP.Net Core 2 ServiceProviderOptions.ValidateScopes Свойство

Не удается разрешить службу с областью действия Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.IViewBufferScope от корневого поставщика

1 Ответ

0 голосов
/ 16 мая 2018

В Core 1.1 не было проверки для Scoped, вложенного в Singleton.

Там было, на самом деле. Но он не был включен по умолчанию. Это было ИМО ошибка в .NET Core 1.

Контекст внутри моей службы Singleton работает нормально.

То, что такая штука работает, довольно необычно, и поэтому блокировка по умолчанию - хорошая вещь. Например, DbContext не является поточно-ориентированным, и поддержание его работоспособным на протяжении всего приложения почти во всех случаях приведет к ошибкам параллелизма, которые будут появляться только при работе в производственной среде, когда одновременно поступает несколько запросов.

Если это не вызывает ошибок в вашей ситуации, это исключение, а не правило.

Не удалось разрешить службу с ограниченным доступом 'ArithmosDaily.IHangfireJobSchedulerService' от корневого поставщика. Я до сих пор не понимаю, что это значит.

Эта ошибка действительно очень запутанная. Это означает, что с контейнером .NET Core вы всегда должны разрешать с IServiceScope, а не с IServiceProvider. При выполнении внутри запроса ASP.NET Core инфраструктура автоматически вызывает от вашего имени ServiceProviderServiceExtensions.CreateScope и использует эту область для разрешения контроллеров и других служб для вас. При запуске вне веб-запроса может потребоваться создать область видимости самостоятельно.

...