异步 SqlConnection - return 除了任务之外的东西

Asynchronous SqlConnection - return something other than a Task

我在 WinForms 应用程序中有一个数据访问层,它查询 SQL 服务器数据库。它包含几个 DAO。在一种特殊情况下,以下方法会引发异常:"BeginExecuteReader requires an open and available Connection. The connection's current state is connecting."

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 语句中,但无济于事。这个想法是在完成数据库操作时有一个响应式 UI ,这已经为这个 class 中的其他方法实现了一些 void return 类型,与async-await 模式。当需要 return 一个对象(或对象集合,如上例)时,如何实现并发?

but it would have to await that as well (wouldn't it?), and so on up the chain

是的,正是这样; 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))
    {
        // ...
    }
}

但请注意,这里有更多 很多 操作是 async 兼容的 - ReadAsync 等。或者为了简单起见,让 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 这样:

var data = await ReadAllProducts();
// do something with "data"