Widzę tutaj różne fragmenty właściwej odpowiedzi, ale pozwólcie, że połączę to wszystko razem i wyjaśnię kilka rzeczy.
Przede wszystkim AcceptChanges
powinno być używane tylko do oznaczania całej transakcji w tabeli jako sprawdzonej i zatwierdzonej. Oznacza to, że jeśli używasz DataTable jako źródła danych do tworzenia powiązań, na przykład z serwerem SQL, AcceptChanges
ręczne wywołanie zagwarantuje, że zmiany nigdy nie zostaną zapisane na serwerze SQL .
To, co sprawia, że ta kwestia jest bardziej zagmatwana, to fakt, że w rzeczywistości istnieją dwa przypadki, w których wyjątek jest zgłaszany i musimy im zapobiegać.
1. Modyfikowanie kolekcji IEnumerable
Nie możemy dodać ani usunąć indeksu do wyliczanej kolekcji, ponieważ może to wpłynąć na wewnętrzne indeksowanie modułu wyliczającego. Istnieją dwa sposoby obejścia tego problemu: albo wykonaj własne indeksowanie w pętli for, albo użyj oddzielnej kolekcji (która nie jest modyfikowana) do wyliczenia.
2. Próba odczytania usuniętego wpisu
Ponieważ DataTables są kolekcjami transakcyjnymi , wpisy można oznaczać do usunięcia, ale nadal pojawiają się w wyliczeniu. Co oznacza, że jeśli poprosisz o usunięty wpis w kolumnie "name"
, zgłosi wyjątek. Co oznacza, że musimy sprawdzić, czy dr.RowState != DataRowState.Deleted
przed zapytaniem o kolumnę.
Kładąc wszystko razem
Moglibyśmy zrobić bałagan i zrobić to wszystko ręcznie, lub możemy pozwolić DataTable wykonać całą pracę za nas i sprawić, by instrukcja wyglądała bardziej jak wywołanie SQL, wykonując następujące czynności:
string name = "Joe";
foreach(DataRow dr in dtPerson.Select($"name='{name}'"))
dr.Delete();
Wywołując Select
funkcję DataTable , nasze zapytanie automatycznie unika już usuniętych wpisów w DataTable. A ponieważ Select
funkcja zwraca tablicę dopasowań, wyliczana przez nas kolekcja nie jest modyfikowana podczas wywołania dr.Delete()
. Doprawiłem również wyrażenie Select za pomocą interpolacji ciągów, aby umożliwić wybór zmiennych bez hałaśliwego kodu.
[ii]
TO[i]
jednak :-)