Ich verstehe nicht, warum dieser Code nicht funktioniert.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
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.
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();
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();
}
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
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
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Bitte beziehen Sie sich auf die Momentaufnahmen, um die Funktionsweise zu verstehen.
Ich hoffe, dass dieses Problem jetzt gelöst wurde.
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.
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();
}
}
}
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
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.
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);
}
}
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.
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++;
}
}
Benutze das:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
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.