Я вижу здесь разные фрагменты правильного ответа, но позвольте мне собрать все воедино и объяснить пару вещей.
Прежде всего, его AcceptChanges
следует использовать только для того, чтобы пометить всю транзакцию в таблице как подтвержденную и зафиксированную. Это означает, что если вы используете DataTable в качестве источника данных для привязки, например, к серверу SQL, то вызов AcceptChanges
вручную гарантирует, что изменения никогда не будут сохранены на сервере SQL .
Что делает эту проблему более запутанной, так это то, что на самом деле существует два случая, в которых возникает исключение, и мы должны предотвратить их оба.
1. Изменение коллекции IEnumerable
Мы не можем добавить или удалить индекс для перечисляемой коллекции, потому что это может повлиять на внутреннюю индексацию перечислителя. Есть два способа обойти это: либо выполнить собственную индексацию в цикле for, либо использовать отдельную коллекцию (которая не изменяется) для перечисления.
2. Попытка прочитать удаленную запись
Поскольку DataTables являются коллекциями транзакций , записи могут быть помечены для удаления, но все равно будут отображаться в перечислении. Это означает, что если вы запросите удаленную запись для столбца, "name"
она выдаст исключение. Это означает, что dr.RowState != DataRowState.Deleted
перед запросом столбца мы должны проверить, есть ли .
Собираем все вместе
Мы можем запутаться и сделать все это вручную, или мы можем позволить DataTable сделать всю работу за нас и заставить оператор выглядеть и больше походить на вызов SQL, выполнив следующие действия:
string name = "Joe";
foreach(DataRow dr in dtPerson.Select($"name='{name}'"))
dr.Delete();
Вызывая Select
функцию DataTable , наш запрос автоматически избегает уже удаленных записей в DataTable. А поскольку Select
функция возвращает массив совпадений, перечисляемая нами коллекция не изменяется при вызове dr.Delete()
. Я также приправил выражение Select интерполяцией строк, чтобы можно было выбирать переменные, не делая код шумным.
[ii]
на[i]
, однако :-)