【问题标题】:How can I loop through a dataset 100 hundred records at a time? C#如何一次遍历数据集 10000 条记录? C#
【发布时间】:2016-09-29 20:48:49
【问题描述】:

我有一个大约 4500 行的数据集。我将它传递给 Web 服务,但在出现性能问题和超时后,我们希望能够一次传递 100 行。

如何在 c# 中实现这一点?

我是否需要将数据集拆分为 100 个表,然后循环遍历这些表,或者是否有更简单的方法一次发送 100 行的集合?

【问题讨论】:

  • DataSet 中有多少个DataTable?一个数据表中有 4,500 个吗?
  • 是的,我现在拥有的一个 DataTable 中有 4500 条记录。现在我正在一次将该数据表传递给一个网络服务......想要将该数据表的 100 行块传递给网络服务

标签: c# loops datatable dataset


【解决方案1】:

您可以使用 Linq,特别是 TakeCopyToDataTable 扩展。

例子:

    DataSet ds = new DataSet();
    DataTable dt = ds.Tables["YOURDATATABLE"];
    IEnumerable<DataRow> firstHundred = dt.AsEnumerable().Take(100);
    // create datatable from query
    DataTable boundTable = firstHundred.CopyToDataTable<DataRow>();
    //call your web service with 1st hundred
    //
    IEnumerable<DataRow> nextHundred = dt.AsEnumerable().Skip(100).Take(100);
    // and so on
    boundTable = nextHundred.CopyToDataTable<DataRow>();
    //call your web service with 1st hundred
    //

以简单的 for 和 Linq 为例,考虑到您有 4,500 行并希望将其按 100 组进行分块:

    DataSet ds = new DataSet();
    DataTable dt = ds.Tables["YOURDATATABLE"];
    IEnumerable<DataRow> firstHundred = dt.AsEnumerable().Take(100);
    // create datatable from query
    DataTable boundTable = firstHundred.CopyToDataTable<DataRow>();
    //call your web service with 1st hundred
    //

    int skipCount = 0;

    for (int i = 1; i <= 45; i++)
    {
        skipCount += 100;
        IEnumerable<DataRow> nextHundred = dt.AsEnumerable().Skip(skipCount).Take(100);
        // create datatable from query
        DataTable boundTable = nextHundred.CopyToDataTable<DataRow>();
        // call web service with next hundred and so on
    }

【讨论】:

  • 所以基本上你在获取块时一遍又一遍地迭代数据行,当然在这种情况下非 linq 解决方案会是更好的方法。
  • 如果您指的是性能,那么是的 - LINQ 可能会慢一些。但是对于 4,500 行 - 我严重怀疑它是否重要。在这种情况下,我提出了 LINQ,因为我认为与一些复杂的循环代码相比,它的代码更短、更易读、更易于维护。
【解决方案2】:
private IEnumerable<IEnumerable<DataRow>> GetChunks(DataTable table, int size)
{
    List<DataRow> chunk = new List<DataRow>(size);

    foreach (DataRow row in table.Rows)
    {
        chunk.Add(row);
        if (chunk.Count == size)
        {
            yield return chunk;
            chunk = new List<DataRow>(size);
        }
    }

    if(chunk.Any()) yield return chunk;
}

//....

DataTable table = dataSet.Tables[yourTable];
var chunks = GetChunks(table, 100);

foreach (IEnumerable<DataRow> chunk in chunks)
    SendChunk(chunk); // <-- Send your chunk of DataRow to webservice

您也可以尝试并行发送数据:

// This would replace the above last two lines
Parallel.ForEach(chunks, chunk => SendChunk(chunk));

虽然我不建议这样做,因为SendChunk 是一个 I/O 操作。

相反,尝试将您的代码转换为async,您可以获得更好的结果:

// Will execute all tasks at the same time
// SendChunk should return a Task
await Task.WhenAll(chunks.Select(chunk => SendChunk(chunk)).ToArray());

【讨论】:

  • 为什么无法识别 chunk.add 或 chunk.any?
  • @JoeStarnes 尝试在源代码顶部添加using System.Linq。另外,请注意方法是帕斯卡大小写表示法,即AddAny
  • 我对 C# 有点陌生,所以请帮助我理解这一点。是否要获取名为 (LPsToCleanup) 的 4,500 行的原始数据集并调用 GetChunks(LPsToCleanup, 100)?这是否会将其分解为 100 行大小的新数据集?
  • @JoeStarnes GetChunks 不接受DataSet 作为参数,你必须传入你的DataTable -> GetChunks(myDataTable, 100)。它不会为您提供大小为 100 的新 DataTable,而是为您提供 DataRow 实例的“块”列表。
  • 嗯,在我将数据表传递给助手之前,还可以......什么数据类型是“块”,因为当我尝试传递它时,它似乎不喜欢那样。
猜你喜欢
  • 2012-02-22
  • 2013-02-21
  • 2021-10-09
  • 2020-01-13
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
相关资源
最近更新 更多