如何使用SqlDataReader像使用SqlDataAdapter一样快地填充DataTable?

时间:2013-10-05 11:00:07

标签: c# sql-server performance dao

我写了一个方法,一旦从DataRow源(使用IDataReader关键字)获取yield,就会返回DataTable。它有效,但它比使用SqlDataAdapter填充public static IEnumerable<DataRow> AsEnumerable(this IDataReader source) { //create columns DataTable dt = new DataTable(); for (int i = 0; i < source.FieldCount; i++) { dt.Columns.Add(source.GetName(i), source.GetFieldType(i)); } //fetch data object[] data = new object[source.FieldCount]; dt.BeginLoadData(); while (source.Read()) { DataRow dr = dt.NewRow(); //this is very slow, bottleneck ? source.GetValues(data); for (int i = 0; i < source.FieldCount; i++) { dr[i] = data[i]; } dt.Rows.Add(dr); yield return dr; } dt.EndLoadData(); } 要慢。

00:08:34.652  //using SqlDataAdapter
00:12:95.153  //using method above

这是结果(250.000行,很多列):

SqlDataAdapter

我怎样才能像使用SqlDataAdapter一样快速地制作它?

为什么我使用它而不是IDataReader:我想在它们来自源时立即处理行,而不是“阻塞”很长时间并等待所有记录都在那里

也许有另一种方法可以做到这一点。注意:我不能简单地产生Item[ColumnName](这很快并且支持我需要的东西:使用{{1}}访问数据,因为数据将被不同的线程加入,所以我需要将它复制到某个地方在搬到下一行之前...

1 个答案:

答案 0 :(得分:1)

我会回答我自己的问题:

提供与使用SqlDataReader类似的性能的方法是使用DataTable.LoadDataRow(object[] values, bool fAcceptChanges)方法。这是使用DataTable方法填充Fill()时内部使用的方法。

它很快,因为它通过直接访问某些内部字段来填充DataRow数据,而使用DataRow索引器(例如:dr[i] = value)将执行多次内部检查。

正如Lorentz所建议的那样,使用ItemArray比使用LoadDataRow()更快但速度仍然比使用{{1}}慢。