Я вижу различные фрагменты правильного ответа здесь, но позвольте мне собрать все вместе и объяснить пару вещей.
Прежде всего, AcceptChanges
следует использовать только для обозначениявся транзакция в таблице как проверенная и подтвержденная.Это означает, что если вы используете DataTable в качестве источника данных для привязки, например, к серверу SQL, то вызов AcceptChanges
вручную гарантирует, что изменения никогда не будут сохранены на сервере SQL . * 1007.*
Что делает эту проблему более запутанной, так это то, что на самом деле есть два случая, в которых выдается исключение, и мы должны предотвратить оба из них.
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();
При вызове функции DataTable Select
наш запрос автоматически избегает ужеудаленные записи в DataTable.А поскольку функция Select
возвращает массив совпадений, коллекция, которую мы перечисляем, не изменяется при вызове dr.Delete()
.Я также добавил в выражение Select строковую интерполяцию, чтобы можно было выбирать переменные без шума в коде.