如何在请求后保持 IdentityDbContext 处于活动状态,以便服务可以使用 UserManager 完成其任务?

问题描述

我从主页调用这样的服务:

_ = _importUserService.AddManyUserAsync(ValidatedUsers);

我希望 Page() 返回并让用户/UI 继续前进,同时服务在后台添加许多使用 UserManager 的用户。问题是,一旦 Page() 返回并且请求完成,IdentityDbContext 就会关闭并且 UserManager 不再起作用。请求完成后,如何让 UserManager 继续工作?

服务使用标准依赖注入:

    private readonly UserManager<ApplicationUser> _userManager;

    public ImportUserService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

如果我使用 await 而不是丢弃并强制服务在页面加载之前完成,则效果很好;但是,如果用户需要等待 2 分钟才能在页面加载之前导入数千个用户,这将是糟糕的用户体验。不依赖于请求的生命周期的服务?

我的想法是创建一个 UserManager 的新实例,而不是依赖于依赖注入的实例,但到目前为止我一直无法让它工作。不确定语法是什么,也找不到在 .net core 3.1 中实际工作的示例

如何在请求后保持 IdentityDbContext 处于活动状态,以便服务可以使用 UserManager 完成其任务? (.Net Core 3.1)

解决方法

来自文档

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio#consuming-a-scoped-service-in-a-background-task

这让我可以运行后台服务,该服务可以调用使用 UserManager 的服务

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .ConfigureServices(services =>
            {
                services.AddHostedService<ConsumeScopedServiceHostedService>();
            });
}
public class ConsumeScopedServiceHostedService : BackgroundService
{
    private readonly ILogger<ConsumeScopedServiceHostedService> _logger;

    public ConsumeScopedServiceHostedService(IServiceProvider services,ILogger<ConsumeScopedServiceHostedService> logger)
    {
        Services = services;
        _logger = logger;
    }

    public IServiceProvider Services { get; }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service running.");

        await DoWork(stoppingToken);
    }

    private async Task DoWork(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service is working.");

        using (var scope = Services.CreateScope())
        {
            var scopedProcessingService = 
                scope.ServiceProvider
                    .GetRequiredService<IScopedProcessingService>();

            await scopedProcessingService.DoWork(stoppingToken);
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service is stopping.");

        await base.StopAsync(stoppingToken);
    }
}

并且工作在 IScopedProcessingService > DoWork(stoppingToken) 中完成 这意味着 ScopedProcessingService 可以访问与使用我的问题中显示的依赖项注入的典型 Web 服务相同的服务。