Как обрабатывать асинхронные исключения при вызове DeleteDocumentAsync - PullRequest
0 голосов
/ 10 октября 2019

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

Как я могу перехватить исключение, вызванное методом DeleteDocumentAsync, чтобы я мог вернутьсоответствующая ошибка вызывающему клиенту?

Спасибо всем заранее!

Код контроллера:

[HttpDelete]
    public ActionResult Delete(Guid key)
        {
            ActionResult result;
            try
            {
               result = StatusCode(StatusCodes.Status200OK);
               _repository.Delete<CodeKeyPairModel>(codeKeyPair);   
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Fatal error deleting record key", ex);
                return StatusCode(StatusCodes.Status500InternalServerError);
            }
        }
</code>

Код репозитория

 public async void Delete<T>(T codeKeyPairModel) where T : CodeKeyPairModel
        {
            var documentLink = UriFactory.CreateDocumentUri(cosmosDBId, collectionId, codeKeyPairModel.Id.ToString());
            var result = await cosmosDBClient.DeleteDocumentAsync(documentLink,
                    new RequestOptions() { PartitionKey = new PartitionKey(Undefined.Value) });
        }

1 Ответ

2 голосов
/ 10 октября 2019

Хранилище должно использовать async Task, а не async void. async void - вот почему вы не можете захватить исключение.

public async Task Delete<T>(T codeKeyPairModel) where T : CodeKeyPairModel {
    var documentLink = UriFactory.CreateDocumentUri(cosmosDBId, collectionId, codeKeyPairModel.Id.ToString());
    var result = await cosmosDBClient.DeleteDocumentAsync(documentLink,
            new RequestOptions() { PartitionKey = new PartitionKey(Undefined.Value) });
}

Ссылка Асинхронное / ожидающее - лучшие практики асинхронного программирования

Асинхронные пустые методы имеют различную семантику обработки ошибок. Когда исключение выдается из метода async Task или async Task<T>, это исключение захватывается и помещается в объект Task. При использовании методов async void объект Task отсутствует, поэтому любые исключения, выброшенные из метода async void, будут вызваны непосредственно для SynchronizationContext, который был активен при запуске метода async void.

Во-вторых, ваш код API выполняет шаблон Fire and Forget, не ожидая выполнения Задачи в Delete. Вам нужно await _respository.Delete.

[HttpDelete]
public async Task<ActionResult> Delete(Guid key)
{
    ActionResult result;
    try
    {
       result = StatusCode(StatusCodes.Status200OK);
       await _repository.Delete<CodeKeyPairModel>(codeKeyPair);   
        return result;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Fatal error deleting record key", ex);
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}
...