Как использовать асинхронные методы с Dependency Injection - PullRequest
0 голосов
/ 07 ноября 2019

Я работаю над веб-приложением .net core (2.2) и у меня есть контроллер, который отвечает за обработку синхронизации данных по требованию . Для этого я сохранил кнопку, при нажатии которой вызывается асинхронный метод службы.

Внутренне этот сервисный вызов обрабатывается ниже действий

  1. Извлекает данные из базы данных для процесса синхронизации данных
  2. Разделение данных на пакеты для пакетного режима обработки синхронизации данных
  3. Подготовка модели данных для соответствующих пакетных данных
  4. Отправка подготовленного пакета данных в целевую очередь сообщений

Для взаимодействия с базой данных изнутри службы, Объект Db-context былпредоставляется с помощью IOC / Dependency Injection, то есть через конструктор .

. Чтобы определить причину проблемы, я выполняю вызовы метода обслуживания, используя множество способов:

  • Вызов асинхронного метода с помощью задачи.Run ()
  • Вызов асинхронного метода без Task.Run ()
  • Вызов метода синхронизации с Task.Run ()
  • Вызов асинхронного метода с ConfigWait (true)

Во всех случаях это не привело к изменениям, все еще получая ObjectDisposedException для объекта DbContext .

При более глубоком понимании системы контекста IOC, мне кажется, что при получении ответа пользователю возвращается область действия для объекта db-context.

Фрагмент кода с минимальными строками представлен ниже:

AzureSearchIndexController.cs

public class AzureSearchIndexController : Controller
{
   [HttpGet]
   public IActionResult StartIndex()
   {
      _azureSearchDataSyncService.StartIndexingAsync(_siteId, _siteName);
   }
}

AzureSearchDataSyncService.cs

public class AzureSearchDataSyncService : IAzureSearchDataSyncService
{
   public AzureSearchDataSyncService(JobContext context,
            ICacheHandler<AzureSearchDataSyncModel> cacheHandler,
            AzureJobsTopicBus azureJobsTopicBus)
   {
      _context = context;
      _cacheHandler = cacheHandler;
      _azureJobsTopicBus = azureJobsTopicBus;
      azureSearchDataSyncModel = new AzureSearchDataSyncModel();
   }

   public async Task StartIndexingAsync(int siteId, string siteName)
   {
      try
      {
         int fetchedData = 0;
         int _batchSize = 10;
         List<AzureJobMessageModel> azureJobMessages = new List<AzureJobMessageModel>();

         var jobsToAdd_Update= GetData(siteId);
         while (dataSyncModel.SyncStatus && 
            fetchedData < jobsToAdd_Update.Count)
         {
            var batchData = jobsToAdd_Update.Skip(fetchedData)
                          .Take(_batchSize - azureJobMessages.Count)
                          .ToList();
            if (batchData.Count <= 0)
               continue;

            azureJobMessages.AddRange( 
               PrepareAzureJobMessageModel( 
                      PrepareAzureSearchIndexerModel(batchData), 
                  EntityActionEnum.updated)
            );

            fetchedData += batchData.Count();

            if (azureJobMessages.Count >= _batchSize)
            {
               //Method sending batch data
               await _azureJobsTopicBus.SendMessageAsync(azureJobMessages);
               dataSyncModel.ProcessedData += azureJobMessages.Count();
               dataSyncModel.ProcessedBatches += 1;
               azureJobMessages = new List<AzureJobMessageModel>();
            }
         }
      }
      catch(Exception ex)
      {
          throw ex;
      }
   }
}

Желаемый результат: Хотите иметь асинхронный режим процесса синхронизации данных при нажатии кнопки.

Фактический результат:

получение ошибки "ObjectDisposedException - Невозможно получить доступ к удаленному объекту (Db-context)"

. У кого-нибудь есть идеи по этому поводу?

Примечание: - Я не хочу делать метод действия асинхронным. Я буду использовать вызовы этого метода либо в служебных методах, либо в действиях CRUD, которые включают логику работы CRUD. Я хочу, чтобы логика синхронизации данных работала в фоновом режиме, не влияя на время отклика для действий CRUD.

1 Ответ

1 голос
/ 07 ноября 2019

Поскольку вызов службы не ожидается, ответ завершается до службы, которая будет распоряжаться контекстом. Вызывает ошибку, когда служба пытается получить доступ к контексту.

Сделайте действие асинхронным, а затем ожидайте службу

public class AzureSearchIndexController : Controller {

    //...

   [HttpGet]
   public async Task<IActionResult> StartIndex() {

        //...

        await _azureSearchDataSyncService.StartIndexingAsync(_siteId, _siteName);

        //...
    }
}
...