【问题标题】:How to delete multiple rows in a DataTable?如何删除数据表中的多行?
【发布时间】:2010-05-26 13:08:57
【问题描述】:

如何在满足自定义条件的 DataTable 行的循环中删除特定的 DataRows - 让我们说具有偶数索引的行 -? (不使用 LINQ)

谢谢

【问题讨论】:

    标签: c# .net ado.net datatable datarow


    【解决方案1】:

    这取决于您所说的“删除”。

    如果您的意思是将它们标记为已删除,只需在循环中访问每一行时调用 Delete() 方法即可。然后,您需要在数据表上调用 AcceptChanges() 以完成删除 - 大概是在您更新数据库之后(如果涉及)。

    foreach( DataRow row in someTable.Rows )
    {
        if( /* your condition here */ )
            row.Delete();
    }
    someTable.AcceptChanges();
    

    如果您的意思是从 DataTable 中删除它,那么您需要分两次这样做:

    List<DataRow> rowsToDelete = new List<DataRow>();
    foreach( DataRow row in someTable.Rows )
    {
        if( /* your condition here */ )
        {
            rowsToDelete.Add( row );
        }
    }
    
    foreach( DataRow row in rowsToDelete )
    {
        someTable.Rows.Remove( row );
    }
    

    值得指出的是,您始终可以使用第一种方法来删除行 - 因为将行标记为 Deleted 然后接受更改会自动将它们从表中删除。但是,有时从Rows 集合中删除DataRow 对象会更加清晰和高效。

    【讨论】:

    • 如果你按照LBushkin所说的那样做,你会看到如下: Collection was modified;枚举操作可能不会执行。所以这是错误的。
    • 只要在将行标记为已删除之前(在 foreach 循环之前)调用 .AcceptChanges(),就不会出现“集合已修改;枚举操作可能无法执行”错误。出现该错误是因为存在需要接受的未决更改。如果您使用 for 循环,则无关紧要,但在这种情况下,最好向后迭代。
    • 第一种方法输出 Szjdw 所说的,但第二种方法就像魔术一样,谢谢布什!
    • 不建议在foreach 循环中使用Remove(),因为该函数会更改集合的状态。
    • 第二个选项就像一个魅力,第一个会出错...
    【解决方案2】:

    试试这个例子

    DataTable table = new DataTable();
    table.Columns.Add("Foo",typeof(int));
    for (int i = 0; i < 10; i++)
        table.Rows.Add(i);
    
    for (int i = table.Rows.Count -1; i >=0; i--)
    {
        // sample removes all even foos
        if ((int)table.Rows[i]["Foo"] % 2 == 0)
            table.Rows.RemoveAt(i);
    }
    

    【讨论】:

    • 如果您将i++ 移动到 for 循环内并且仅在不删除时增加,也可以执行前向循环 (0 -> Count-1)。 if (...) remove() else i++
    【解决方案3】:

    如果您想要一个比上述建议更短的解决方案,请尝试遍历结果列表,并使用像 sub(x) 这样的 lambda 来删除每一行。

    dt.Select("Column1 > 0").ToList.ForEach(Sub(x) dt.Rows.Remove(x))
    

    【讨论】:

      【解决方案4】:

      另一种方法是

          DataRow[] DrArrCheck = DataTableName.Select("ID > 0");
          foreach(DataRow DrCheck in DrArrCheck)
          {
              DataTableName.Rows.Remove(DrCheck);
          }
      

      【讨论】:

        【解决方案5】:
         public static void DeleteRowsFromDataTable(DataTable dataTable, string columnName, string columnValue)
                {
                    IEnumerable<DataRow> dataRows = (from t in dataTable.AsEnumerable()
                                                     where t.Field<string>(columnName) == columnValue
                                                     select t);
                    foreach (DataRow row in dataRows)
                        dataTable.Rows.Remove(row);
                }
        

        【讨论】:

          【解决方案6】:

          要删除多行(例如 100,000 行中的 50,000 行),复制数据库比执行 datatable.Rows.Remove(row) 或 row.Delete() 快得多。例如:

          DataRow[] rowsToKeep = datatable.Select("ID > 50000");
          DataTable tempDataTable= rowsToKeep.CopyToDataTable;
          dataTable.Clear();
          dataTable.Merge(tempDataTable);
          tempDataTable.Dispose();
          

          【讨论】:

            【解决方案7】:

            尝试迭代 Select() 的结果。这与其他答案非常相似,但我觉得它最直接

            DataRow[] r = table.Select();
            for (int i = 0; i < r.Length; i++)
            {
                if (i % 2 == 0)
                    r[i].Delete();
            }
            

            【讨论】:

              【解决方案8】:

              我一直使用 LBushkin 的“两阶段”方法,我最终决定为它编写一个函数是值得的:

                  public delegate bool DataRowComparer(DataRow dr);
              
                  public static void RemoveDataRows(DataTable table, DataRowComparer drc)
                  {
                      List<DataRow> RowsToRemove = new List<DataRow>();
                      foreach (DataRow dr in table.Rows)
                          if (drc(dr))
                              RowsToRemove.Add(dr);
                      foreach (DataRow dr in RowsToRemove)
                          table.Rows.Remove(dr);
                  }
              

              现在我可以用一行代码删除行(例如):

              RemoveDataRows(dt, row => row["StringVal"].ToString() == "B" && (Int16)(row["NumberVal"]) >= 4);
              

              如果这对任何人都有帮助...

              (感谢任何进一步缩写的方法。)

              【讨论】:

                【解决方案9】:

                我就是这样做的。

                    for (int i = RowNumber.Count - 1; i >= 0; i--)
                                        {
                                            dt.Rows.RemoveAt(Int32.Parse(RowNumber[i]));
                                        }
                
                                        missingNotesGV.DataSource = dt;
                
                                        missingNotesGV.DataBind();
                

                反向执行 for 循环很重要,否则如果除了其他位置的行之外还要删除末尾的行,则会出现错误。

                【讨论】:

                  【解决方案10】:

                  当我遇到这个问题时,我就是这样做的。

                  Dim index As Integer = 0
                  Dim count As Integer = resultsDT.Rows.Count - 1
                  For i As Integer = 0 To count
                      If resultsDT.Rows(index).Item("something") = "something" Then                               
                          resultsDT.Rows(index).Delete()
                          resultsDT.AcceptChanges()
                          index = index - 1
                      End If
                      index = index + 1
                      i = i + 1
                  Next
                  

                  【讨论】:

                    【解决方案11】:

                    试试这个

                    foreach(DataRow oRow in YourDataTable.Rows)
                    {
                      if ("Check You Condition")
                       {
                          YourDataTable.Rows.Remove(oRow);
                       }
                    }
                    

                    【讨论】:

                    • 在使用 foreach 循环遍历集合时,您不能修改集合。
                    猜你喜欢
                    • 2014-06-19
                    • 1970-01-01
                    • 2011-02-16
                    • 2018-09-21
                    • 2018-10-28
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多