Асинхронный SqlConnection - возвращает что-то отличное от Задачи - PullRequest
1 голос
/ 28 апреля 2020

У меня есть слой доступа к данным в приложении WinForms, которое запрашивает базу данных SQL Server. Содержит несколько DAO. В одном конкретном случае следующий метод вызывает исключение: «BeginExecuteReader требует открытого и доступного соединения. Текущее состояние соединения - соединение».

public List<Product> readAllProducts()
{
    List<Product> products = new List<Product>();
    string queryGetAllProducts = "SELECT * FROM Products;";

    using (SqlConnection conn = new SqlConnection(Configuration.CONNECTION_STRING))
    {
        SqlCommand cmd = new SqlCommand(queryGetAllProducts, conn);

        try
        {
            conn.OpenAsync();

            Task<SqlDataReader> readerTask = cmd.ExecuteReaderAsync();
            SqlDataReader reader = readerTask.Result;
            while (reader.Read())
            {
                 // read the data...
            }
        }
        catch (SqlException sqlEx)
        {
           throw;
        }
        finally 
        {
            if (conn != null)
                conn.Close();
        }
    }
}

В приведенном выше примере я попытался обернуть выполнение запрос в выражении lock, безрезультатно. Идея состоит в том, чтобы во время выполнения операций с базой данных иметь отзывчивый пользовательский интерфейс, что уже было достигнуто для других методов этого класса, которые имеют void возвращаемых типов с шаблоном async - await. Как может быть достигнут параллелизм при необходимости вернуть объект (или коллекцию объектов, как в случае выше)?

1 Ответ

2 голосов
/ 28 апреля 2020

но это тоже должно было бы ждать (не так ли?) И так далее по цепочке

Да, именно это; await заразно. Таким образом, вы получите:

public async Task<List<Product>> ReadAllProducts()
{
    List<Product> products = new List<Product>();
    string queryGetAllProducts = "SELECT * FROM Products;";

    using (SqlConnection conn = new SqlConnection(Configuration.CONNECTION_STRING))
    {
        // ...
    }
}

, но отметьте, что lot больше операций здесь async -совместимо - например, ReadAsync et c , Или, чтобы упростить задачу, просто попросите Dapper сделать тяжелую работу:

public async Task<List<Product>> ReadAllProducts()
{
    using (var conn = new SqlConnection(Configuration.CONNECTION_STRING))
    {
        var products = await conn.QueryAsync<Product>("SELECT * FROM Products;");
        return products.AsList();
    }
}

Тогда ваше использование вызовов await this:

var data = await ReadAllProducts();
// do something with "data"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...