Асинхронные методы в .net core api - PullRequest
0 голосов
/ 18 декабря 2018

Я использую Dapper для подключения .net core api к Oracle DB. У меня есть следующие методы.

public IDbConnection GetConnection()
    {
        var connectionString = configuration.GetSection("ConnectionStrings").GetSection("AsyncDB").Value;
        var conn = new OracleConnection(connectionString);
        return conn;
    }

public Object GetProducts()
    {
        //throw new System.NotImplementedException();
        object result = null;
        try
        {
            OracleDynamicParameters dynamicParameters = new OracleDynamicParameters();
            dynamicParameters.Add("EMPCURSOR", OracleDbType.RefCursor, ParameterDirection.Output);

            var conn = this.GetConnection();
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }

            if (conn.State == ConnectionState.Open)
            {
                var query = "SPGETPRODUCTINFO";
                result = SqlMapper.Query(conn, query, param: dynamicParameters, commandType: CommandType.StoredProcedure);
            }
        }
        catch (Exception e)
        {
            throw e;
        }

        return result;
    }

Процедура SPGETPRODUCTINFO возвращает строки из базы данных.

Что такоеспособы превратить метод в асинхронный метод с использованием ключевых слов async / await?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Вы делаете этот метод асинхронным так же, как и любой другой метод асинхронным.Вы помечаете метод как асинхронный, чтобы он возвращал Task, если он возвращает void или Task, где T - это класс, который он ранее возвращал.Измените его, чтобы использовать синхронные версии любых доступных методов и ожидать результатов.

Ваша обработка исключений здесь не является хорошей.Во-первых, вы делаете throw e;, где e - пойманное исключение.Не делай этого.Если вам нужно сбросить пойманную исключительную ситуацию, просто наберите throw;.Таким образом вы сохраните свой след стека.Кроме того, эта попытка / улов абсолютно бессмысленна.Если вы не собираетесь предпринимать какие-либо корректирующие действия или что-либо регистрировать, это бессмысленно.Вы можете полностью удалить try / catch из этого кода.

Вы неправильно обрабатываете соединение с базой данных.OracleConnection реализует IDisposable .Вам нужно либо использовать оператор using, либо удалить его в блоке finally.

Имя класса говорит: GetProducts, но вы просто возвращаете объект.Это не очень хорошоТеперь любой потребляющий код должен будет привести его к правильному типу, чтобы использовать его.Весь смысл Dapper в том, что он может сопоставить ваш запрос со строго типизированным объектом.Основываясь на названии этого метода, вы должны возвращать IEnumerable или что-то в этом роде.

Вы проверяете состояние соединения с базой данных сразу после его получения.Там нет смысла в этом.Если вы получили новое соединение, вы можете предположить, что оно закрыто и вам нужно его открыть.

Принимая все это во внимание, вы должны получить что-то вроде этого:

public IDbConnection GetConnection()
{
    var connectionString = configuration.GetSection("ConnectionStrings").GetSection("AsyncDB").Value;
    var conn = new OracleConnection(connectionString);
    return conn;
}

public Task<IEnumerable<Product>> GetProducts()
{
    OracleDynamicParameters dynamicParameters = new OracleDynamicParameters();
    dynamicParameters.Add("EMPCURSOR", OracleDbType.RefCursor, ParameterDirection.Output);

    const string query = "SPGETPRODUCTINFO";

    using (var conn = this.GetConnection())
    {
        await conn.OpenAsync();
        var products = await conn.QueryAsync<Product>(query, param: dynamicParameters, commandType: CommandType.StoredProcedure);
        return products;
    }
}

Сейчасчто GetProducts является асинхронным, любой метод выше, который вызывает его, должен быть асинхронным и изменен, чтобы возвращать задачу и ожидать ее.И любой метод, который вызывает асинхронный вызов и должен быть изменен, чтобы вернуть задачу и ожидать ее.Весь путь вверх по стеку вызовов, пока не дойдете до обработчика событий или основного метода для вашего приложения.

0 голосов
/ 18 декабря 2018

Прежде всего, ваш метод необходимо преобразовать в Async

public Object GetProducts()

в

public async Task<Object> GetProductsAsync();
public async Task<Object> GetProductsAsync(CancellationToken cancellationToken = default(CancellationToken));

Если метод поддерживает реализацию Async, общие соглашения показывают, что имя метода заканчивается наКлючевое слово Async.

Вы можете проверить методы, имеют ли они реализацию Async.Например, если SqlMapper.Query имеет асинхронную реализацию, обычно это похоже на SqlMapper.QueryAsync.

Дальнейшие асинхронные реализации имеют тип возвращаемого значения Task.для обработки асинхронной реализации вы можете сделать это

result = await SqlMapper.QueryAsync(conn, query, param: dynamicParameters, commandType: CommandType.StoredProcedure);

Кроме того, если вы хотите, чтобы ваш метод поддерживал аннулирование, тогда вам нужно иметь CancellationToken cancellationToken = default(CancellationToken) в качестве параметра и ваш метод будет

result = await SqlMapper.QueryAsync(conn, query, param: dynamicParameters, commandType: CommandType.StoredProcedure, cancellationToken: cancellationToken);
...