it-swarm.com.de

Sicheres Entfernen von DataRow in ForEach

Ich verstehe nicht, warum dieser Code nicht funktioniert.

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}
37
Jack Kada

Bei den meisten Sammlungen in .NET können Sie den Inhalt der Sammlung nicht ändern, während Sie sie durchlaufen. Aus den docs für IEnumerator :

Ein Enumerator bleibt solange gültig. Die Sammlung bleibt unverändert. Ob Änderungen werden an der Sammlung vorgenommen, B. hinzufügen, ändern oder löschen Elemente ist der Enumerator unwiderruflich ungültig gemacht und der nächste Aufruf von MoveNext oder Reset wirft eine InvalidOperationException. Wenn der Sammlung wird zwischen .__ geändert. MoveNext und Current, Current gibt .__ zurück. das Element, auf das es eingestellt ist, auch wenn Der Enumerator ist bereits ungültig.

Die beste Lösung ist in der Regel, eine separate Sammlung (z. B. einen List<DataRow>) von Elementen zu erstellen, die Sie entfernen möchten, und diese dann zu entfernen, nachdem Sie das Iterieren beendet haben.

32
Jon Skeet

Am sichersten ist die Verwendung der for-Schleife

for (int i = datatable.Rows.Count - 1; i >= 0; i--) 
{
    if (true)
    {
        datatable.Rows[i].Delete();
    }
}

Vergessen Sie nicht, AcceptChanges , um alle markierten Zeilen zu entfernen:

datatable.AcceptChanges();
47
VMAtm

Sie können eine Auflistung nicht ändern, während Sie mit einer foreach-Anweisung iterieren.

sie können so etwas versuchen:

List<DataRow> deletedRows = new List<DataRow>();

foreach (DataRow dataRow in dataTable.Rows)
{
    if(true) deletedRows.Add(dataRow);
}

foreach(DataRow dataRow in deletedRows)
{
    dataRow.Delete();
}
19
Thibault Falise

Wenn Sie die delete-Methode aufrufen, müssen Sie nach der foreach-Schleife nur AcceptChanges() in der Tabelle aufrufen, die Sie ändern. 

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}

dataTable.AcceptChanges();

Die Löschmethode markiert einfach die Zeile zum Löschen.

http://msdn.Microsoft.com/de-de/library/system.data.datarow.delete%28v=VS.90%29.aspx

9
Chris

meine Antwort ist möglicherweise nicht mehr nützlich. Ausnahmewurf in Foreach mit DataRow erscheint nur in .NET 2.0 und früheren Versionen. Der Grund ist die Beschreibung unter msdn http://msdn.Microsoft.com/en-us /library/system.data.datarow.delete(v=vs.80).aspx

Wenn der Zeilenstatus der Zeile hinzugefügt wird, wird die Zeile aus der Tabelle entfernt.

Der RowState wird gelöscht, wenn Sie die Delete-Methode verwenden. Es bleibt so lange gelöscht, bis Sie AcceptChanges aufrufen.

Eine gelöschte Zeile kann durch Aufrufen von RejectChanges rückgängig gemacht werden.

um dieses Problem zu lösen, können Sie DataTable.AcceptChanges () aufrufen, bevor Sie foreach verwenden

4
neverlandx
foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}

dataTable.AcceptChanges();

Bitte beziehen Sie sich auf die Momentaufnahmen, um die Funktionsweise zu verstehen.

  1. Nur gelöscht, aber nicht aus der DataTable entfernt.

enter image description here

  1. Haltepunkt vor AcceptChanges () - Funktion .enter image description here
  2. Nach dem Ausführen von AcceptChanges () Funktion .enter image description here

Ich hoffe, dass dieses Problem jetzt gelöst wurde.

2

Es gibt eine andere Version (ich denke eine einfachere), was ich gerade verwendet habe:

int i=0;
while (i < myDataTable.Rows.Count)
{
    if (condition)  //should it be deleted?
        myDataTable.Rows.RemoveAt(i);
    else
        i++;
}

Das geht schneller.

1
Jettero

Nur für Leute, die nach einem bestimmten Szenario wie mir suchen. Ich musste die Zeit verkürzen, und sobald aus jeder Zeile nützliche Informationen extrahiert wurden, habe ich die Zeile ausgeschlossen, indem ich sie als gelöscht markiere.

Hoffe das hilft jemandem ...

foreach (DataRow dataRow in dataTable.Rows)
{
    if (dataRow.RowState != DataRowState.Deleted)
    {
        if (your condition here)
        {
            dataRow.Delete();
        }
    }
}
1
Kay Lee

Dies erreichen Sie am einfachsten, indem Sie eine Liste verwenden, um die Zeilen, die Sie löschen möchten, zuzuordnen und dann Zeilen außerhalb der DataTable-Iteration zu löschen.

C #

    List<DataRow> rowsWantToDelete= new List<DataRow>();

    foreach (DataRow dr in dt.Rows)
    {
        if(/*Your condition*/)
        {
            rowsWantToDelete.Add(dr);
        }
    }

    foreach(DataRow dr in rowsWantToDelete)
    {
        dt.Rows.Remove(dr);
    }

VB

Dim rowsWantToDelete As New List(Of DataRow)

For Each dr As DataRow In dt
    If 'Your condition' Then
        rowsWantToDelete .Add(dr)
    End If
Next

For Each dr As DataRow In rowsWantToDelete 
    dt.Rows.Remove(dr)
Next
1
Nishantha

Der Inhalt von Rows ändert sich während der Iteration, wenn Sie eine Zeile löschen, wodurch die Iteration ungültig wird.

Sie können jedoch die Zeilen zuerst in eine Auflistung kopieren, dann die Auflistung durchlaufen und die Zeilen auf diese Weise löschen. Dadurch wird sichergestellt, dass die Iteration nicht durch Ändern der zu iterierenden Daten unterbrochen wird.

1
Lucero

Dies ist so, weil es so aussieht, als würde man versuchen, die Treppe der Treppe, die man besteigt, zu zerlegen. Sie können ein Element, das Sie wiederholen, einfach nicht entfernen.

Daher sollten Sie ein anderes Array verwenden, um sie zu iterieren und aus der datablen Rows-Eigenschaft zu entfernen.

foreach (DataRow dataRow in dataTable.Select())
{
    if (true)
    {
        dataTable.Rows.Remove(dataRow);
    }
}
0
iBener

Wo Elemente eine Count haben, habe ich Folgendes getan:

int Count = myTable.Rows.Count;

while (Count > 0) // replace condition with myTable.Rows.Count if unconditionally performed on all rows
{
    DataRow row = myTable.Rows[0] // or however you want to find your index

    // do some work
    myTable.Rows.Remove(row);

    // if you want to perform a check to break out of while
    if (someCondition)
        Count = 0;
    else
        Count = myTable.Rows.Count;
}

Beachten Sie, dass bei Objekten, die eine .GetXXXX()-Sammlung haben, wie FileInfo (IIRC), das Löschen von Elementinhalten in einer foreach zulässig ist. Eine Lösung, die ich in Betracht gezogen habe, ist das Erstellen einer Erweiterungsmethode, die eine .GetItems()-Methode bereitstellt. 

0
IAbstract

Sicher Magents

So habe ich es gemacht und funktioniert gut

dt = GetStationeryConsolidationDetails(txtRefNo.Text);
int intRows = dt.Rows.Count;
int x = 0;
for (int c = 0; c < intRows; c++)
{
  if (dt.Rows[c - x]["DQTY"].ToString() == "0")
  {
    dt.Rows[c - x].Delete();
    dt.AcceptChanges();
    x++;        
  }
}
0
Sam

Benutze das:

for (int i = 0; i < myDataTable.Rows.Count; i++)

{

 myDataTable[i].Delete();

}
0
1111

Dies gilt für fast jede Sammlung. Wenn Sie versuchen, ein Element zu löschen, während Sie die Sammlung durchlaufen, liegt ein Problem vor. Wenn Sie beispielsweise Zeile 3 löschen, wird aus der vorherigen Zeile 4 die Zeile 3.

0
DOK