鉴于以下代码,我对最佳实践提出了一些问题:
string connectionString = @"Server=(local)\sqlexpress; Database=master; Integrated Security=true;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlDataAdapter dataAdapter = new SqlDataAdapter("select * from information_schema.columns", connection))
{
await connection.OpenAsync();
DataTable dataTable = new DataTable();
await Task.Run(() => dataAdapter.Fill(dataTable));
return dataTable;
}
}
我已经看过几个在Task.Run()调用中包装整个代码块的示例,但我不确定它是否比仅调用Task.Run()更好对于DataAdapter.Fill()方法,它感觉更灵活和特定(仅使用等待异步任务)。
在Fill()方法上调用Task.Run()的方法比包装整个代码块更好吗?
在Task.Run()中调用Fill()是否有任何负面影响?如果Fill()有错误,我会想到丢失调用堆栈和/或异常信息的内容。
有没有更好的方法在ASP.NET中编写它?
答案 0 :(得分:1)
在ASP.NET中,使用Task.Run
几乎没有帮助。究竟会改善什么?它只引入了开销。
也就是说,Fill
将执行IO(耗尽数据读取器),因此可能想要异步调用它。不幸的是,这种方法没有异步版本。
如果您坚持使用异步IO(which is questionable for database access),则需要找到替代方案。也许异步实体框架或原始ADO.NET可以帮助您。
答案 1 :(得分:0)
您是否尝试过使用DataReader和新的ExecuteReaderAsync?我记得是SqlDataAdapter在没有异步的情况下在内部使用了DataReader。如果可能的话,您可能还想完全跳过使用DataTable来减少一些开销。
对于很少更改此类查询架构列的小型结果集,我可能会以多种方式之一将其缓存在Web服务器上。哎呀,对于架构更改,您甚至可以创建一个简单的DDL触发器来更新带有时间戳字段的单行表,以便让您知道已经进行了更改,然后只在必要时运行查询。对于除模式表之外的表,另一个选项是CHECKSUM_AGG。