1

我写了一个方法,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],因为数据将被不同的线程访问,所以我需要在移动到下一行之前将其复制到某处......

4

1 回答 1

1

我会回答我自己的问题:

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

它很快,因为它DataRow通过直接访问一些内部字段来填充数据,同时使用 DataRow 索引器(例如:dr[i] = value)会做几次内部检查。

正如 Lorentz 所建议的, usingItemArray比 indexer 快,但仍然比 using 慢LoadDataRow()

于 2013-10-10T13:00:04.917 回答