2014-08-28 26 views
12

考虑下面的代码,我对最佳实践的一些问题:在ASP.NET中异步填充DataSet或DataTable的最佳实践是什么?

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()调用,但我不当然,如果这比仅仅为DataAdapter.Fill()方法调用Task.Run()更好,它更加灵活和具体(只在异步任务中使用await)。

是否比包装整个代码块更好地调用Fill()方法上的Task.Run()方法?

在Task.Run()中调用Fill()是否有任何负面影响?如果Fill()有错误,我正在考虑丢失调用堆栈和/或异常信息。

有没有更好的方式来写在ASP.NET中?

+1

为什么不把所有的代码放在一个异步方法中?也就是说,移动任务以包含整个SQL连接生命周期,包括填充DataTable。 – user2864740 2014-08-28 22:04:49

+1

这是ASP.NET还是GUI? – usr 2014-08-28 22:14:28

+0

@usr,我假设ASP.NET;这里有很大的区别吗? – 2014-08-29 01:14:16

回答

1

在ASP.NET中,它几乎永远不会帮助使用Task.Run。它会改善什么?它只引入开销。

也就是说,Fill将执行IO(耗尽数据读取器),因此您可能想要异步调用它。不幸的是,这种方法没有异步版本。

如果你坚持使用异步IO(which is questionable for database access),你需要找到一个替代方案。也许异步实体框架或原始ADO.NET可以帮助你。

0

您是否尝试过使用DataReader和新的ExecuteReaderAsync?我记得的是SqlDataAdapter已经在内部使用DataReader而没有异步。如果可能的话,您可能还想完全跳过使用DataTable来减少一些开销。

对于很少改变这种查询架构列的小型结果集,我可能会以多种方式之一将其缓存到Web服务器上。对于模式更改,您甚至可以创建一个简单的DDL触发器来使用时间戳字段更新单个行表,以便让您知道已做出更改,然后只在必要时运行查询。对于模式表以外的表,另一个选项是CHECKSUM_AGG。