Я пытаюсь сделать рабочий сервис как windows сервис. Задача: 1. Проверить таблицу БД, если в ней есть строки, в которых столбцы «State» готовы - обработать эти строки. 2. Запустите sqltabledependency к уведомлениям об изменениях в db для обработки новых или обновленных строк.
Вот мой код.
Worker.cs
public class Worker : BackgroundService
{
private static readonly string Directory = AppDomain.CurrentDomain.BaseDirectory;
private readonly ILogger<Worker> _logger;
private readonly IServiceProvider _provider;
private ICommandDispatcher _commandDispatcher;
private IQueryDispatcher _queryDispatcher;
private readonly SmtpOptions _smtpOptions;
public Worker(ILogger<Worker> logger, IServiceProvider provider)
{
_logger = logger;
_provider = provider;
_smtpOptions = new SmtpOptions(...);
using (IServiceScope scope = _provider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
_commandDispatcher = scope.ServiceProvider.GetService<ICommandDispatcher>();
_queryDispatcher = scope.ServiceProvider.GetService<IQueryDispatcher>();
}
}
private async Task<OutgoingLetter> GetCurrentLetter()
{
return await _queryDispatcher.HandleAsync<LetterGetQuery, OutgoingLetter>(new LetterGetQuery());
}
private async Task ProcessLetterTask()
{
OutgoingLetter letter = null;
do
{
try
{
letter = await GetCurrentLetter();
if (letter != null)
{
if (letter.MessageTypeID == MessageTypes.Auth)
await _commandDispatcher.HandleAsync(new AuthLetterProcessCommand(letter, _smtpOptions));
if (letter.MessageTypeID == MessageTypes.Rests)
await _commandDispatcher.HandleAsync(
new RestsLetterProcessCommand(Directory, letter, _smtpOptions));
}
}catch (Exception ex)
{
await _commandDispatcher.HandleAsync(new LetterErrorProcessCommand(letter));
}
} while (letter != null);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await ProcessLetterTask();
string connection = "...my connection string";
var tableName = "OutgoingLetters";
var tableDependency = new SqlTableDependency<OutgoingLetter>(connection, tableName, "Queues");
tableDependency.OnChanged += OnNotificationReceived;
tableDependency.Start();
}
private void OnNotificationReceived(object sender, RecordChangedEventArgs<OutgoingLetter> e)
{
if (e.ChangeType == ChangeType.Insert || e.ChangeType == ChangeType.Update)
{
Task.WhenAll(ProcessLetterTask());
}
}
}
}
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
string connection = "Server=MS-SQL2;Database=GoodWill_New;Trusted_Connection=True;";
services.AddDbContext<QueuesDbContext>(options => options.UseSqlServer(connection));
services.AddScoped<ICommandHandler<LetterProcessCommand>, LetterProcessCommandHandler>();
services.AddScoped<ICommandHandler<LetterErrorProcessCommand>, LetterErrorProcessCommandHandler>();
services.AddScoped<ICommandHandler<LetterSuccessProcessCommand>, LetterSuccessProcessCommandHandler>();
services.AddScoped<ICommandHandler<OneCErrorLetterProcessCommand>, OneCErrorLetterProcessCommandHandler>();
services.AddScoped<IQueryHandler<LetterGetQuery, OutgoingLetter>, LetterGetQueryHandler>();
services.AddScoped<ICommandDispatcher, CommandDispatcher>();
services.AddScoped<IQueryDispatcher, QueryDispatcher>();
services.AddHostedService<Worker>();
});
}
LetterGetQueryHandler.cs
internal sealed class LetterGetQueryHandler: IQueryHandler<LetterGetQuery, OutgoingLetter>
{
private readonly QueuesDbContext _queuesDbContext;
public LetterGetQueryHandler(QueuesDbContext queuesDbContext)
{
_queuesDbContext = queuesDbContext;
}
public async Task<OutgoingLetter> HandleAsync(LetterGetQuery query)
{
return await _queuesDbContext.Letters.FirstOrDefaultAsync(x => x.QueueStateID == QueueStates.Ready);
}
}
Все обработчики команд имеют одинаковую структуру - метод HandleAsyn c и используют QueueDbContext. Теперь я получаю исключение объекта. Возникло исключение: System.ObjectDisposedException в System.Private.CoreLib.dll. Имя объекта: IServiceProvider. Я думаю, что он не может внедрить QueuesDbContext в обработчики, но я понятия не имею, как его исправить. Спасибо за любой совет