2013-10-05 41 views
1

我写了一个方法,它从IDataReader源(使用yield关键字)获取后立即返回DataRow。它可以工作,但它的确比使用SqlDataAdapter填充DataTable慢。如何使用SqlDataReader像使用SqlDataAdapter一样快地填充DataTable?

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]访问数据,因为数据将由不同的线程加入,所以我需要在移动到下一行之前将它复制到某处...

+0

也许它会更快,只是做source.GetData(dr.ItemArray); –

+0

好的建议。我要试试这个。我在提出这个问题之前所尝试的是使用DataRow.ItemArray [i](内部for循环)填充DataRow,它非常慢。 – tigrou

+0

它稍微快一点,我得到9.6和10.5秒(好),但它仍然总是比SqlDataAdapter慢(即使几次尝试后) – tigrou

回答

1

我会回答我的问题:。

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

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

正如洛伦兹所建议的,使用ItemArray比索引器更快,但它仍比使用LoadDataRow()慢。

相关问题