Dapper QueryAsyn c с CancellationToken должен работать должным образом - PullRequest
0 голосов
/ 02 августа 2020

Я использую Dapper (версия 1.50.5) в веб-API ASP. NET, выполняя некоторые SQL асинхронно. Я заметил, что запрос не отменяется после того, как отмена инициирована клиентом.

Я знаю, что это был топи c раньше (например, CancellationToken с asyn c методами Dapper ? ), но даже после обращения к различным аналогичным статьям я не смог понять проблему или найти решение.

Вот несколько фрагментов кода.

Обратите внимание что

objectDirector.ReadAsync(id, cancellationToken);

передает отмену, принятую

ExecuteQueryAsync(CancellationToken cancellationToken)

Контроллер:

    [HttpPost]
    [Route("api/Forms/{id}/Data")]
    [CompressFilter]
    public async Task<IHttpActionResult> GetDataAsync(int id, CancellationToken cancellationToken)
    {
        if (!forms.IsAuthorized(id, uniqueId, Constants.Roles.Operator))
        {
            return StatusCode(HttpStatusCode.Forbidden);
        }

        if (!forms.Exists(id))
        {
            return NotFound();
        }

        var dynamicObjects = await objectDirector.ReadAsync(id, cancellationToken);

        return Ok(dynamicObjects);
    }

Запрос исполняемый код:

    public async Task<IEnumerable<dynamic>> ExecuteQueryAsync(CancellationToken cancellationToken)
    {
        var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

        using (var connection = new SqlConnectionFactory().CreateConnection(Form.DatabaseId))
        {
            try
            {
                tokenSource.CancelAfter(new TimeSpan(0, 4, 0));

                await connection.OpenAsync(tokenSource.Token);

                var sql = SqlQueryBuilder.ToString();

                var command = new CommandDefinition(sql, commandTimeout: 240, cancellationToken: tokenSource.Token);

                return await connection.QueryAsync(command);
            }
            catch (SqlException exception)
            {
                var messageTemplate = "Exception: {Method}, {DataSource}, {Database}; Form: {Id}, {Name}";

                Logger.Error(exception, messageTemplate, "Dynamic Object Reader: Execute Query", connection.DataSource, connection.Database, Form.Id, Form.Name);

                throw;
            }
            finally
            {
                tokenSource.Dispose();
            }
        }
    }

Когда я заменяю код выполнения запроса на al oop, который проверяет статус отмены, а затем завершает процесс, если этот статус изменился, он работает, как ожидалось. Однако, когда я выполняю приведенный выше код, он не завершает выполнение запроса к базе данных, ни для запроса отмены из клиентского приложения, ни для отмены через 4 минуты.

...