Я пытаюсь создать запланированное задание, которое выполняет команду Sql. Фактический запланированный процесс работает нормально, однако у моего dbcontext есть проблема, из-за которой он не может получить доступ к базе данных.
Он получит контекст со всеми соответствующими таблицами, но любое действие в таблицах выдает InvalidOperationException
. При попытке проверить любой из элементов таблицы в режиме отладки все они также говорят InvalidOperationException
с красным X
в качестве значка.
Я также пытался отправить команду через команду и обработчик MediatR
но с такими же ошибками. Каждая попытка изменения кода приводила к одной и той же ошибке без отклонений.
Это моя первая попытка создания фоновых служб, для справки я следовал учебному пособию https://thinkrethink.net/2018/02/21/asp-net-core-background-processing/
Startup.cs
// truncated
services.AddDbContext<MyDbContext>();
services.AddSingleton<IHostedService, Daily_Task>();
Фоновая служба
namespace MyApi.ScheduledTasks
{
public abstract class BackgroundService : IHostedService
{
private Task _executingTask;
private readonly CancellationTokenSource tokenSource = new CancellationTokenSource();
public virtual Task StartAsync(CancellationToken token)
{
_executingTask = ExecuteAsync(tokenSource.Token);
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
}
public virtual async Task StopAsync(CancellationToken token)
{
if (_executingTask == null)
return;
try
{
tokenSource.Cancel();
}
finally
{
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, token));
}
}
protected virtual async Task ExecuteAsync(CancellationToken token)
{
do
await Process();
while (!token.IsCancellationRequested);
}
protected abstract Task Process();
}
}
Процессор с областью действия
namespace MyApi.ScheduledTasks
{
public abstract class ScopedProcessor: BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
public ScopedProcessor(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
protected override async Task Process()
{
using (var scope = _scopeFactory.CreateScope())
{
await ProcessInScope(scope.ServiceProvider);
}
}
public abstract Task ProcessInScope(IServiceProvider provider);
}
}
Задача, которую нужно запланировать
namespace MyApi.ScheduledTasks
{
public class Daily_Task : ScopedProcessor
{
private DateTime Start => DateTime.Now;
private DateTime NextTask { get; private set; }
public Daily_Task(IServiceScopeFactory scopeFactory) : base(scopeFactory)
{
NextTask = SetNextRun(Start);
}
// currently doing minutes for testing
private DateTime SetNextRun(DateTime date) => date.AddMinutes(1);
public override async Task ProcessInScope(IServiceProvider provider)
{
try
{
using (var context = provider.GetRequiredService<MyDbContext>())
{
// even this causes an error
var data = context.MyTable.Any();
}
}
catch (Exception e)
{
Log.Error(e);
}
await Task.CompletedTask;
}
protected override async Task ExecuteAsync(CancellationToken token)
{
do
{
var now = DateTime.Now;
if (now > NextTask)
{
await Process();
NextTask = SetNextRun(now);
}
}
while (!token.IsCancellationRequested);
}
}
}