ASP.NET Core 3.0 выполняет логику при запуске приложения - PullRequest
0 голосов
/ 14 октября 2019

У меня есть записи базы данных, для каждой из которых у меня должны быть повторяющиеся задания при запуске приложения. Я думал, что смогу сделать это, используя IHostedService и DI'ing сервис области, но это невозможно, потому что мой сервис области имеет меньший срок службы. IHostedService требуется одноэлементная служба, которая приводит к тупику, потому что ApplicationDbContext требует сервис с областью действия.

InvalidOperationException: Невозможно использовать сервис с ограниченным диапазоном 'Binance.Services.IBotService' из одноэлементного 'Microsoft.Extensions.Hosting. .IHostedService '.

Мне просто нужно выполнить эту логику при запуске приложения. Что лучше в таких сценариях?

namespace Binance.Services
{
    public class BotHostedService : IHostedService
    {
        private readonly ILogger _logger;
        private readonly IBotService _botService;

        private int _numberOfBots;

        public BotHostedService(ILogger<BotHostedService> logger, IBotService botService)
        {
            _logger = logger;
            _botService = botService;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Bot service is starting.");

            var bots = await _botService.GetAllAsync();
            _numberOfBots = bots.Count;

            for (int i = 0; i < _numberOfBots; i++)
            {
                Bot bot = bots[i];
                _logger.LogDebug($"{bot.Name} is starting. Symbol: {bot.CryptoPair.Description}, Interval: {bot.TimeInterval.Description}");
                RecurringJob.AddOrUpdate($"bot{i}", () => DoWork(bot), $"0/5 * * * *", TimeZoneInfo.Local);
            }
        }

        public void DoWork(Bot bot)
        {
            _logger.LogError($"{bot.Name} is working. Current time: {DateTime.Now.ToLocalTime()}");
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Bot service is stopping.");

            for (int i = 0; i < _numberOfBots; i++)
            {
                RecurringJob.RemoveIfExists($"bot{i}");
            }

            return Task.CompletedTask;
        }
    }
}

Ответы [ 2 ]

1 голос
/ 14 октября 2019

Это описано в разделе Использование службы с областями действия в фоновой задаче Фоновые задачи с размещенными службами в ASP.NET Core . Ответ заключается в создании области внутри службы, когда это необходимо. Для этого необходимо добавить IServiceProvider к зависимостям сервиса, например:

public class BotHostedService : IHostedService
{
    //...
    private readonly IServiceProvider  _services;

    public BotHostedService(IServiceProvider services, ILogger<BotHostedService> logger)
    {
        _logger = logger;
        _services=services;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Bot service is starting.");
        using (var scope = _services.CreateScope())
        {
            var botService = scope.ServiceProvider
                                  .GetRequiredService<IBotService>();
            var bots = await _botService.GetAllAsync();
            ...
        }
    }
1 голос
/ 14 октября 2019

Вы можете внедрить IServiceProvider через конструктор, а затем создать область при необходимости, например так:

using (var scope = this.serviceProvider.CreateScope())
{
    IBotService botService = scope.ServiceProvider.GetRequiredService<IBotService>();
    // use it
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...