【问题标题】:How to partitioning or splitting DataTable in C#?如何在 C# 中对 DataTable 进行分区或拆分?
【发布时间】:2011-12-29 06:04:29
【问题描述】:

我想拆分 DataTable 以便我可以将它的块从一个地方上传到另一个地方。

例如

选择前 100 行。
选择接下来的 100 行。
选择接下来的 100 行,依此类推...

有没有办法像数据库中的游标一样做到这一点?我不喜欢使用循环等来计算行数。

【问题讨论】:

标签: c# sql datatable


【解决方案1】:

YourDataTable.Select() 给你一个数据数组

linq 呢?

例如,YourDataTable.Select (x => x).Take (100).ToEnumerable() 为您提供前 100 个 DataRows 和接下来的 100 个 YourDataTable.Select (x => x).Skip(100).Take (100).ToEnumerable()

【讨论】:

  • .Skip(100).Take(100)一样使用Skip()
  • @Yahia,收到错误消息“无法将 lambda 表达式转换为类型‘字符串’,因为它不是委托类型”。看起来 lambda 表达式不能在 DataTable.Select() 方法中使用。
  • 你假设它总是100?
【解决方案2】:

试试这个:

public static class DataExtensions
{
    public static IEnumerable<IEnumerable<DataRow>> Partition(this DataTable dataTable, int partitionSize)
    {
        var numRows = Math.Ceiling((double)dataTable.Rows.Count);
        for(var i = 0; i < numRows / partitionSize; i++)
        {
            yield return Partition(dataTable, i * partitionSize, i * partitionSize + partitionSize);
        }
    }
    private static IEnumerable<DataRow> Partition(DataTable dataTable, int index, int endIndex)
    {
        for(var i = index; i < endIndex && i < dataTable.Rows.Count; i++)
        {
            yield return dataTable.Rows[i];
        }
    }
}
var partitions = dataTable.Partition(100);

在做:

dataTable.Skip(0).Take(100);
dataTable.Skip(100).Take(100);
dataTable.Skip(200).Take(100);
dataTable.Skip(300).Take(100);

将迭代 0 次,并在第一次执行时取 100。然后遍历 100 行,取 100,然后迭代 200 行,然后取 100,以此类推。

上面会做一个惰性提取,并且每行只命中一次

【讨论】:

  • 这是性能的最佳答案,如上文所述,使用多个 linq 调用将导致整个数据集的额外不必要迭代。这个答案避免了这个问题。
  • 如何将其转换为 vb.net?
  • 我该如何实现foreach (DataRow row in dataTable.Skip(300).Take(100))
【解决方案3】:

这是一种简单的方法:

public DataSet test(DataSet ds, int max)
    {
        int i = 0;
        int j = 1;
        DataSet newDs = new DataSet();
        DataTable newDt = ds.Tables[0].Clone();
        newDt.TableName = "Table_" + j;
        newDt.Clear();
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            DataRow newRow = newDt.NewRow();
            newRow.ItemArray = row.ItemArray;

            newDt.Rows.Add(newRow);
            i++;
            if (i == max)
            {
                newDs.Tables.Add(newDt);
                j++;                    
                newDt = ds.Tables[0].Clone();
                newDt.TableName = "Table_" + j;
                newDt.Clear();
                i = 0;
            }
        }
        return newDs;
    }

你可以试试吗?

【讨论】:

  • 在返回 newDs 之前,您需要添加最后一个 newDt!
  • 这段代码有一个重大缺陷:它只将创建的DataTable添加到表列表中一次i == max,这意味着除非表大小可以被块大小整除,否则不会添加最后一个DataTable。为了纠正移动/添加 newDs.Tables.Add(newDt);在创建两个表之后立即进行
【解决方案4】:

使用 linq 选择记录的一部分 堆栈溢出中的此链接可能会有所帮助 Split a collection into n parts with LINQ?

【讨论】:

    【解决方案5】:

    检查:splitting a large datatable into smaller batches from c-sharpcorner.com

    internal static List<datatable> SplitTable(DataTable originalTable, int batchSize)
        {
            List<datatable> tables = new List<datatable>();
    
            DataTable new_table = new DataTable();
            new_table = originalTable.Clone();
            int j = 0;
            int k = 0;
    
            if (originalTable.Rows.Count &lt;= batchSize)
            {
                new_table.TableName = "Table_" + k;
                new_table = originalTable.Copy();
                tables.Add(new_table.Copy());
            }
            else
            {
                for (int i = 0; i &lt; originalTable.Rows.Count; i++)
                {
                    new_table.NewRow();
                    new_table.ImportRow(originalTable.Rows[i]);
                    if ((i + 1) == originalTable.Rows.Count)
                    {
                        new_table.TableName = "Table_" + k;
                        tables.Add(new_table.Copy());
                        new_table.Rows.Clear();
                        k++;
                    }
                    else if (++j == batchSize)
                    {
                        new_table.TableName = "Table_" + k;
                        tables.Add(new_table.Copy());
                        new_table.Rows.Clear();
                        k++;
                        j = 0;
                    }
                }
            }
    
            return tables;
        }
    

    【讨论】:

      【解决方案6】:
      Improving on  @vanessa
      
      public DataSet SplitDataTable(DataTable tableData, int max)
              {
                  int i = 0;
                  int j = 1;
                  int countOfRows = tableData.Rows.Count;
                  DataSet newDs = new DataSet();
                  DataTable newDt = tableData.Clone();
                  newDt.TableName = tableData.TableName+"_" + j;
                  newDt.Clear();
                  foreach (DataRow row in tableData.Rows)
                  {
                      DataRow newRow = newDt.NewRow();
                      newRow.ItemArray = row.ItemArray;
      
                      newDt.Rows.Add(newRow);
                      i++;
      
                      countOfRows--;
      
                      if (i == max )
                      {
                          newDs.Tables.Add(newDt);
                          j++;
                          newDt = tableData.Clone();
                          newDt.TableName = tableData.TableName + "_" + j;
                          newDt.Clear();
                          i = 0;
                      }
      
                      if (countOfRows == 0 && i < max)
                      {
                          newDs.Tables.Add(newDt);
                          j++;
                          newDt = tableData.Clone();
                          newDt.TableName = tableData.TableName + "_" + j;
                          newDt.Clear();
                          i = 0;
                      }
                  }
                  return newDs;
              }
      

      【讨论】:

      • 欢迎来到 Stack Overflow!请不要把你的源代码扔在这里。友善一点,并尝试对您的答案进行漂亮的描述,以便其他人会喜欢并支持它。见:How do I write a good answer?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      • 2013-08-29
      • 2021-11-17
      • 1970-01-01
      • 2014-08-31
      • 2017-11-25
      相关资源
      最近更新 更多