Подтвердить что ты не робот

Любой недостаток использования ExecuteReaderAsync из С# AsyncCTP

Есть несколько статей, которые указывают, что асинхронные вызовы базы данных - плохая идея в .NET.

В С# Async CTP существует расширение System.Data.SqlClient.SqlCommand, называемое ExecuteReaderAsync. У меня есть некоторые операции, как показано ниже в моем существующем коде:

var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

using (var conn = new SqlConnection(connectionString)) {
    using (var cmd = new SqlCommand()) {

        cmd.Connection = conn;
        cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        conn.Open();

        var reader = cmd.ExecuteReader();
        while (reader.Read()) {

            //do the reading

        }

        conn.Close();
    }
}

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

Но, с другой стороны, я не вижу большой привлекательности в этом подходе (возможно, я не смотрю в правильном направлении, кто знает!).

Итак, есть ли недостатки в использовании этой новой модели программирования асинхронного программирования здесь?

Edit:

Предполагая, что я реорганизую код, как показано ниже:

public async Task<IEnumerable<Foo>> GetDataAsync() { 

    List<Foo> foos = new List<Foo>();

    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

    using (var conn = new SqlConnection(connectionString)) {
        using (var cmd = new SqlCommand()) {

            cmd.Connection = conn;
            cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            conn.Open();

            var reader = await cmd.ExecuteReaderAsync();
            while (reader.Read()) {

                //do the reading
                //create foos

            }

            conn.Close();
        }
    }

    return foos;

}

Насколько я понимаю из ключевого слова await, он преобразует код, который после него, как продолжение. Кроме того, когда он попадает в ключевое слово ожидания, он немедленно возвращается к своему вызывающему абоненту независимо от состояния операции. Когда он заканчивается, он возвращается и запускает код продолжения.

Это то, что я имею в виду.

4b9b3361

Ответ 1

Я не согласен с Рикой в ​​этом. Команды Async DB не только хороши, они имеют решающее значение для достижения масштаба, пропускной способности и задержки. Его возражение относительно времени нарастания пула потоков применяется только к веб-серверу, который испытывает небольшие объемы трафика.

В ситуации с высоким уровнем трафика (которая является единственной, которая имеет значение) пулу потоков не придется ждать "впрыскивания" новых потоков. Выполнение SQL-команд асинхронно важно не только с точки зрения запросов веб-серверов/потоков, но и с точки зрения общего времени жизни/ожидания ожидания: некоррелированные вызовы БД могут выполняться параллельно, а не последовательно. Это само по себе приводит, как правило, к резким улучшениям в латентности HTTP-запроса, как это испытывает пользователь. Другими словами, ваши страницы загружаются быстрее.

Слово рекомендации: команда SQL не является асинхронной, пока вы не включите Asynchronous Processing=true в строке подключения. Хотя это не установлено (и по умолчанию это не так, Edit: начиная с .NET Framework < 4.5. Asynchronous Processing больше не требуется) ваши "асинхронные" вызовы BeginExecuteReader - не что иное, как притворство, вызов запустит поток и заблокирует этот поток. Когда в строке соединения включена истинная обработка асинхронизации, вызов действительно асинхронный, и обратный вызов основан на завершении ввода-вывода.

Предупреждение: команда async SQL завершается, как только первый результат возвращается клиенту, а информационные сообщения считаются результатом.

create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount
as
begin
print 'Hello';
select complex query;
end

Вы потеряли все преимущества async. print создает результат, который отправляется обратно клиенту, который завершает команду async и выполнение на клиенте возобновляется и продолжается с помощью функции reader.Read(). Теперь это будет заблокировано, пока сложный запрос не начнет давать результаты. Вы спрашиваете: кто ставит print в процедуру? но print может быть замаскирован во что-то еще, возможно, что-то невинно выглядящее как INSERT, которое выполняется без предварительного выпуска SET NOCOUNT ON.