我写了一个方法,DataRow
它在从IDataReader
源中获取后立即返回(使用yield
关键字)。它可以工作,但它确实比DataTable
使用 a填充要慢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();
}
这是结果(250.000 行,很多列):
00:08:34.652 //using SqlDataAdapter
00:12:95.153 //using method above
我怎样才能让它和使用一样快SqlDataAdapter
?
为什么我使用它而不是SqlDataAdapter
:我想在行来自源时立即处理它们,而不是“阻塞”很长时间并等待所有记录都在那里。
也许还有另一种方法可以做到这一点。注意:我不能简单地产生一个IDataReader
(它很快并且支持我需要的东西:使用访问数据Item[ColumnName]
,因为数据将被不同的线程访问,所以我需要在移动到下一行之前将其复制到某处......