我写了一个方法,一旦从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}}访问数据,因为数据将被不同的线程加入,所以我需要将它复制到某个地方在搬到下一行之前...
答案 0 :(得分:1)
我会回答我自己的问题:
提供与使用SqlDataReader
类似的性能的方法是使用DataTable.LoadDataRow(object[] values, bool fAcceptChanges)
方法。这是使用DataTable
方法填充Fill()
时内部使用的方法。
它很快,因为它通过直接访问某些内部字段来填充DataRow
数据,而使用DataRow索引器(例如:dr[i] = value)
将执行多次内部检查。
正如Lorentz所建议的那样,使用ItemArray
比使用LoadDataRow()
更快但速度仍然比使用{{1}}慢。