使用存储在列上的数据填充C#DataTable的最快方法是什么?

时间:2017-05-16 10:01:10

标签: c# .net datatable

我有一个DataTable对象,我需要根据存储在列流中的数据来填充 - 即流最初包含DataTable的模式,然后是按列组织的值

目前,我采取了相当天真的方法

  • 创建足够的空行来保存所有数据值。
  • 每个单元格填充这些行。

结果是每单元格迭代,至少可以说不是特别快。

那是:

// Create rows first...
// Then populate...
foreach (var col in table.Columns.Cast<DataColumn>)
{
    List<object> values = GetValuesfromStream(theStream);

    // Actual method has some DBNull checking here, but should 
    // be immaterial to any solution.
    for (var i=0; i<values.Count; i++)
        table.Rows[i][col] = values[i];
}

我的猜测是每个列的后备DataStorage项目都没有随着行的添加而扩展,但是随着值被添加到每个列,但我还远未确定。有关加载此类数据的任何提示。

请注意,首先加载所有列表然后逐行读取可能不合理 - 首先要采用这种方法来减少序列化巨大DataTable个对象时可能导致的内存异常,抓住整个数据网格的克隆并将其读入可能只会将问题转移到其他地方。对于原始表和另一列值,肯定有足够的内存,但可能没有DataTable的两个副本。

1 个答案:

答案 0 :(得分:1)

虽然我没有找到避免迭代单元格的方法,但根据上面的评论,我发现写入已添加到表格中的DataRow项目的原因是这是一个坏主意,并且是我观察到的绝大部分减速的原因。

我使用的最终方法最终看起来像这样:

List<DataRow> rows = null;
// Start population...
var cols = table.Columns.Cast<DataColumn>.Where(c => string.IsNullOrEmpty(c.Expression));
foreach (var col in cols)
{
    List<object> values = GetValuesfromStream(theStream);
    // Create rows first if required.
    if (rows == null)
    {
        rows = new List<DataRow>();
        for (var i=0; i<values.Count; i++)
            rows.Add(table.NewRow());
    }
    // Actual method has some DBNull checking here, but should 
    // be immaterial to any solution.
    for (var i=0; i<values.Count; i++)
       rows[i][col] = values[i];
}
rows.ForEach(r => table.Rows.Add(r));

这种方法解决了两个问题:

  1. 如果您尝试将空DataRow添加到具有空限制或类似限制的表中,那么您将收到错误消息。这种方法确保所有数据在添加之前都存在,这应该可以解决大多数此类问题(尽管我还没有必要检查它如何与自动递增PK列一起使用)。
  2. 如果涉及表达式,则在已添加到表的行的行状态更改时评估这些表达式。因此,在每次将值添加到单元格(昂贵且毫无意义)时重新计算所有表达式之前,现在所有计算都在添加所有基础数​​据后仅进行一次。
  3. 由于我使用的表格没有使用DataTable类/模型的那些功能,因此写入桌面时可能会出现其他并发症。但对于简单的情况,这很有效。