在Camilo Terevinto的回答基础上,我想异步处理从异步读取器(DataTable.Load
)加载数据表的操作。
我创建了一个SqlCommand
扩展,以每次读取一条记录的方式读取数据。虽然数据仍然同步加载,但使用ReadAsync
进行异步迭代,每次迭代一条记录。
public static class SqlExtensions
{
public static async Task<DataTable> FillDataTableAsync(this SqlCommand cmd)
{
DataTable dt = null;
using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
{
DataTable schemaTable = await reader.GetSchemaTableAsync();
dt = new DataTable();
foreach (DataRow row in schemaTable.Rows)
dt.Columns.Add(row.Field<string>("ColumnName"), row.Field<Type>("DataType"));
while (await reader.ReadAsync())
{
DataRow dr = dt.Rows.Add();
foreach (DataColumn col in dt.Columns)
dr[col.ColumnName] = reader[col.ColumnName];
}
}
return dt;
}
}
并且像这样使用它:
DataTable dt = null;
using (SqlCommand cmd = new SqlCommand("SELECT * FROM TABLE", conn))
{
dt = await cmd.FillDataTableAsync();
}
如果我需要异步更新DataTable
,我会先删除记录,然后在事务内使用SqlBulkCopy
的WriteToServerAsync(dt)
方法。
using (SqlCommand cmd = new SqlCommand("DELETE FROM TABLE", transaction.Connection))
{
cmd.Transaction = transaction;
await cmd.ExecuteNonQueryAsync();
}
using (SqlBulkCopy copy = new SqlBulkCopy(transaction.Connection, SqlBulkCopyOptions.Default, transaction))
{
copy.DestinationTableName = "TABLE";
await copy.WriteToServerAsync(dt);
}
注意:我尚未测试其效率与SqlDataAdapter
相比。
O'Brien
的人这样的天真数据问题,并且它们有助于提高性能。其次,这种态度会导致其他项目中出现糟糕的代码,当它确实很重要时。参数只是正确的做法。学会正确使用它们并在您的常见数据模式中考虑它们,这样当仅用于娱乐的代码突然变得真实时,您已经在正确的方式下进行操作了。 - Joel Coehoorn