异步填充DataTable?

时间:2018-03-02 22:38:21

标签: c# .net-core

我在.NET Core 2.0应用程序中有以下功能。

public DataTable CallDb(string connStr, string sql)
{
    var dt = new DataTable();
    var da = new SqlDataAdapter(sql, connStr);
    da.Fill(dt);
    return dt;
}

如何将其转换为异步函数?

public async Task<DataTable> CallDb(string connStr, string sql)
{
    var dt = new DataTable();
    var da = new SqlDataAdapter(sql, connStr);
    da.Fill(dt); // No FillAsync to await?
    return dt;
}

我需要使用DataTable因为sql可能会返回不同架构的数据。有没有更好的方法来处理动态模式?

2 个答案:

答案 0 :(得分:5)

SqlDataAdapter从未更新为包含方法的TPL版本。你可以这样做:

await Task.Run(() => da.Fill(dt));

但那会创建一个无用的线程。

一个好的方法是使用这样的东西:

public async Task<DataTable> CallDb(string connStr, string sql)
{
    var dt = new DataTable();
    var connection = new SqlConnection(connStr);
    var reader = await connection.CreateCommand().ExecuteReaderAsync();
    dt.Load(reader);

    return dt;
}

当然,应该进行一些更改,例如using语句。但是,在这里,您正在以正确的方式使用异步调用。

答案 1 :(得分:1)

尽管在这种情况下不会阻塞对ExecuteReaderAsync()的初始调用,但是dt.Load(reader)可能等效于reader.Read()而不是await reader.ReadAsync(),并且可能在检索行。

如果您确实需要DataTable来与外部API配合使用,或者因为您事先不知道字段定义,但是需要完全异步的行为,那么最好使用自己的代码来构造一个DataTable,添加所需的列,例如基于reader.GetName()reader.GetFieldType(),然后使用await reader.ReadAsync()dt.Rows.Add()在循环中填充行。