Ich möchte einige Zeilen aus DataTable löschen, aber es gibt einen Fehler wie diesen:
Sammlung wurde geändert; Aufzählungsoperation wird möglicherweise nicht ausgeführt
Ich benutze zum Löschen dieses Codes,
foreach(DataRow dr in dtPerson.Rows){
if(dr["name"].ToString()=="Joe")
dr.Delete();
}
Also, was ist das Problem und wie kann es behoben werden? Welche Methode raten Sie?
c#
delete-row
namco
quelle
quelle
[ii]
zu[i]
:-)DataTable
später verwenden, wird es eine Ausnahme auslösen. Der richtige Weg wäre,Remove()
die Quelle aufzurufenDataTable
-dtPerson.Rows.Remove(dr)
.Delete()
keinen Aufruf vonAcceptChanges()
, damit die Löschung wirksam wird?Bevor alle auf den Zug " Sie können keine Zeilen in einer Aufzählung löschen " springen, müssen Sie zunächst erkennen, dass DataTables transaktional sind , und Änderungen erst dann technisch bereinigen, wenn Sie AcceptChanges () aufrufen.
Wenn diese Ausnahme beim Aufrufen von Löschen angezeigt wird , befinden Sie sich bereits in einem Datenstatus mit ausstehenden Änderungen . Wenn Sie beispielsweise gerade aus der Datenbank geladen haben, würde der Aufruf von Löschen eine Ausnahme auslösen, wenn Sie sich in einer foreach-Schleife befinden.
ABER! ABER!
Wenn Sie Zeilen aus der Datenbank laden und die Funktion ' AcceptChanges () ' aufrufen , übernehmen Sie alle ausstehenden Änderungen an der DataTable. Jetzt können Sie die Liste der Zeilen, die Delete () aufrufen, ohne Rücksicht auf die Welt durchlaufen, da die Zeile lediglich zum Löschen vorgesehen ist, aber erst festgeschrieben wird, wenn Sie AcceptChanges () erneut aufrufen.
Mir ist klar, dass diese Antwort etwas veraltet ist, aber ich musste mich kürzlich mit einem ähnlichen Problem befassen und hoffe, dass dies einem zukünftigen Entwickler, der an 10 Jahre altem Code arbeitet, einige Schmerzen erspart :)
Ps Hier ist ein einfaches Codebeispiel, das von Jeff hinzugefügt wurde :
C #
VB.Net
quelle
object row_loopVariable in ds.Tables(0).Rows
umDataRow row in ds.Tables(0).Rows
counter++
anstelle voncounter+= 1
.mit dieser Lösung:
Wenn Sie die Datentabelle nach dem Löschen der Zeile verwenden, wird eine Fehlermeldung angezeigt. Was Sie also tun können, ist: Ersetzen
dr.Delete();
durchdtPerson.Rows.Remove(dr);
quelle
Das funktioniert bei mir,
quelle
ich hoffe es hilft dir
quelle
drow.Delete();
nichtdrow.delete();
Methoden unterscheiden zwischen Groß- und Kleinschreibung in .net übrigensOder konvertieren Sie einfach eine DataTable- Zeilensammlung in eine Liste:
quelle
Gehen Sie folgendermaßen vor , um die gesamte Zeile aus DataTable zu entfernen
quelle
Wo liegt das Problem: Es ist verboten, Elemente aus der Sammlung innerhalb einer foreach-Schleife zu löschen.
Lösung: Machen Sie es entweder so, wie Widor es geschrieben hat, oder verwenden Sie zwei Schleifen. Beim ersten Durchlauf von DataTable speichern Sie nur (in einer temporären Liste) die Verweise auf Zeilen, die Sie löschen möchten. Im zweiten Durchgang über Ihre temporäre Liste löschen Sie diese Zeilen.
quelle
quelle
Ich weiß, dass dies eine sehr alte Frage ist, und ich habe vor einigen Tagen eine ähnliche Situation.
Problem war, in meiner Tabelle sind ca. 10000 Reihen, so dass das Schleifen durch
DataTable
Reihen sehr langsam war.Schließlich fand ich eine viel schnellere Lösung, bei der ich eine Kopie der Quelle
DataTable
mit den gewünschten Ergebnissen, der klaren QuelleDataTable
und denmerge
Ergebnissen von temporärDataTable
in die erste Quelle erstelle.Anmerkung : Statt für die Suche
Joe
inDataRow
namensname
Sie haben für alle Datensätze , die nicht haben Namen suchenJoe
(wenig entgegengesetzte Art und Weise des Suchens)Es gibt Beispiel (
vb.net
):Ich hoffe, dass diese kürzere Lösung jemandem hilft.
Es gibt
c#
Code (nicht sicher, ob er korrekt ist, da ich den Online-Konverter verwendet habe :():Natürlich habe ich für den
Try/Catch
Fall, dass es kein Ergebnis gibt (zum Beispiel, wenn IhrdtPerson
es nicht enthältname
Joe
, eine Ausnahme auslöst), verwendet, damit Sie nichts mit Ihrer Tabelle tun, bleibt es unverändert.quelle
Ich habe einen Datensatz in meiner App und habe Änderungen vorgenommen (eine Zeile löschen), der jedoch
ds.tabales["TableName"]
schreibgeschützt ist. Dann habe ich diese Lösung gefunden.Es ist eine wpf
C#
App,quelle
Sie versuchen dies, um die ID-Spalte abzurufen und aus der Datentabelle zu entfernen
quelle
Ich sehe hier verschiedene Teile der richtigen Antwort, aber lassen Sie mich alles zusammenbringen und ein paar Dinge erklären.
Zunächst
AcceptChanges
sollte nur verwendet werden, um die gesamte Transaktion in einer Tabelle als validiert und festgeschrieben zu markieren. Wenn Sie also die DataTable als DataSource zum Binden an beispielsweise einen SQL Server verwenden, wird durchAcceptChanges
manuelles Aufrufen sichergestellt, dass die Änderungen niemals auf dem SQL Server gespeichert werden .Was dieses Problem verwirrender macht, ist, dass es tatsächlich zwei Fälle gibt, in denen die Ausnahme ausgelöst wird und wir beide verhindern müssen.
1. Ändern der Sammlung eines IEnumerable
Wir können der Aufzählung keinen Index hinzufügen oder entfernen, da dies die interne Indizierung des Enumerators beeinträchtigen kann. Es gibt zwei Möglichkeiten, dies zu umgehen: Führen Sie entweder Ihre eigene Indizierung in einer for-Schleife durch oder verwenden Sie eine separate Sammlung (die nicht geändert wird) für die Aufzählung.
2. Versuch, einen gelöschten Eintrag zu lesen
Da es sich bei DataTables um Transaktionssammlungen handelt , können Einträge zum Löschen markiert werden, erscheinen jedoch weiterhin in der Aufzählung. Das heißt, wenn Sie einen gelöschten Eintrag für die Spalte
"name"
anfordern, wird eine Ausnahme ausgelöst. Das heißt, wir müssen prüfen, ob,dr.RowState != DataRowState.Deleted
bevor wir eine Spalte abfragen.Alles zusammenfügen
Wir könnten chaotisch werden und all das manuell erledigen, oder wir könnten die DataTable die ganze Arbeit für uns erledigen lassen und die Anweisung wie einen SQL-Aufruf aussehen lassen, indem wir Folgendes tun:
Durch den Aufruf der DataTable-
Select
Funktion vermeidet unsere Abfrage automatisch bereits gelöschte Einträge in der DataTable. Und da dieSelect
Funktion ein Array von Übereinstimmungen zurückgibt, wird die Sammlung, über die wir aufzählen, beim Aufruf nicht geändertdr.Delete()
. Ich habe auch den Select-Ausdruck mit String-Interpolation aufgepeppt, um eine Variablenauswahl zu ermöglichen, ohne den Code verrauschen zu lassen.quelle