我在.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;
}
Run Code Online (Sandbox Code Playgroud)
如何将其转换为异步函数?
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;
}
Run Code Online (Sandbox Code Playgroud)
我需要使用,DataTable因为sql可能会返回具有不同架构的数据。还有什么更好的方式来处理动态模式?
SqlDataAdapter从未更新为包括方法的TPL版本。您可以这样做:
await Task.Run(() => da.Fill(dt));
Run Code Online (Sandbox Code Playgroud)
但这将创建一个无用的线程。
一个好的方法是使用类似以下的内容:
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;
}
Run Code Online (Sandbox Code Playgroud)
当然,using应该进行一些更改,例如声明。但是,这里您使用正确的方式使用异步调用。
小智 7
尽管在这种情况下最初的调用ExecuteReaderAsync()不会阻塞,dt.Load(reader)但可能会执行相当于reader.Read()而不是的操作await reader.ReadAsync(),并且可能会在检索行时阻塞调用线程。
如果您确实需要 aDataTable与外部 API 一起使用,或者因为您事先不知道字段定义,但需要完全异步行为,那么您最好使用自己的代码来构造 a DataTable,添加所需的列,例如基于reader.GetName()和,然后使用和reader.GetFieldType()循环填充行。await reader.ReadAsync()dt.Rows.Add()