30

How can I delete specific DataRows within a loop of a DataTable rows which meet a custom condition -lets say the rows having an index of even number-? (Without using LINQ)

Thanks

pencilCake
  • 51,323
  • 85
  • 226
  • 363

11 Answers11

63

It depends on what you mean by 'delete'.

If you mean mark them as deleted, just call the Delete() method on each row as you visit it in your loop. You then need to call AcceptChanges() on the data table to finalize the delete - presumably after you update your database (if one is involved).

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

If you mean remove it from the DataTable, then you need to do so in two passes:

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 );
}

It's worth pointing out that you can always use the first method to remove rows - since marking rows as Deleted and then accepting changes will automatically remove them from the table. But, sometimes it is more clear and efficient to simply remove the DataRow objects from the Rows collection.

LBushkin
  • 129,300
  • 32
  • 216
  • 265
  • 4
    If you do the same as what LBushkin said,you will see as follow: Collection was modified; enumeration operation might not execute. so it is wrong. – Szjdw Jan 25 '13 at 12:48
  • 2
    As long as you call .AcceptChanges() prior to marking rows as deleted (before the foreach loop) then you will not get the "Collection was modified; enumeration operation might not execute" error. The error appears because there are pending changes that need to be accepted. If you use a for loop then it won't matter but in that case it would be best to iterate backwards. – Soenhay May 22 '13 at 19:48
  • the first method outputs what Szjdw said but the second one works like magic, thanks Bush! – Albert Laure Dec 12 '13 at 05:44
  • 2
    Using of `Remove()` is not recommended in a `foreach` loop since the function changes the state of the collection. – Mstislav Toivonen Mar 19 '15 at 17:40
  • The second option works like a charm, the first one will give an error... – Mufaddal Feb 28 '19 at 13:17
10

Try something like this example

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);
}
Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • Could also do a forward loop (0 -> Count-1) if you move the `i++` inside the for loop and only increment when not deleting. `if (...) remove() else i++` – CuppM May 26 '10 at 14:14
5

If you want a shorter solution than those proposed above, try looping over the list of results, and using a lambda like sub(x) to remove each of those rows.

dt.Select("Column1 > 0").ToList.ForEach(Sub(x) dt.Rows.Remove(x))
Barett
  • 5,826
  • 6
  • 51
  • 55
Sergey
  • 179
  • 2
  • 4
4

The other way is

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

To delete multiple rows (for instance 50,000 out of 100,000) it is much quicker to copy the database than to do either datatable.Rows.Remove(row) or row.Delete(). For instance:

DataRow[] rowsToKeep = datatable.Select("ID > 50000");
DataTable tempDataTable= rowsToKeep.CopyToDataTable;
dataTable.Clear();
dataTable.Merge(tempDataTable);
tempDataTable.Dispose();
tval
  • 412
  • 3
  • 17
1
 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);
        }
Vin
  • 942
  • 8
  • 13
0

I always used LBushkin's "two-phase" approach and I finally decided it was worth it to write a function for it:

    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);
    }

And now I can delete rows with one line of code (for example):

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

In case this helps anyone...

(And any ways to further abbreviate are appreciated.)

0

try iterating over the result of Select(). This is pretty similar to other answers, but I find it the most direct

DataRow[] r = table.Select();
for (int i = 0; i < r.Length; i++)
{
    if (i % 2 == 0)
        r[i].Delete();
}
Kleinux
  • 1,511
  • 10
  • 22
0

This is how I do it.

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

                        missingNotesGV.DataSource = dt;

                        missingNotesGV.DataBind();

Its important to do the for loop in reverse otherwise you get errors if you're removing rows at the end in addition to rows in other places.

toly P
  • 44
  • 7
-1

This is how I did it when I ran into this issue.

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
tweakch
  • 426
  • 3
  • 13
Jordan
  • 11
  • 1
-2

try this

foreach(DataRow oRow in YourDataTable.Rows)
{
  if ("Check You Condition")
   {
      YourDataTable.Rows.Remove(oRow);
   }
}
Johnny
  • 1,555
  • 3
  • 14
  • 23