Estou vendo vários pedaços da resposta certa aqui, mas deixe-me juntar tudo e explicar algumas coisas.
Em primeiro lugar, AcceptChanges
deve ser usado apenas para marcar a transação inteira em uma tabela como sendo validada e confirmada. O que significa que se você estiver usando o DataTable como um DataSource para vinculação a, por exemplo, um servidor SQL, chamar AcceptChanges
manualmente garantirá que as alterações nunca serão salvas no servidor SQL .
O que torna esse problema mais confuso é que, na verdade, há dois casos em que a exceção é lançada e temos que evitar os dois.
1. Modificando a coleção de um IEnumerable
Não podemos adicionar ou remover um índice da coleção que está sendo enumerada porque isso pode afetar a indexação interna do enumerador. Há duas maneiras de contornar isso: faça sua própria indexação em um loop for ou use uma coleção separada (que não seja modificada) para a enumeração.
2. Tentativa de ler uma entrada excluída
Como DataTables são coleções transacionais , as entradas podem ser marcadas para exclusão, mas ainda aparecem na enumeração. O que significa que, se você solicitar uma entrada deletada para a coluna "name"
, será lançada uma exceção. O que significa que devemos verificar se dr.RowState != DataRowState.Deleted
antes de consultar uma coluna.
Juntando tudo
Podemos bagunçar e fazer tudo isso manualmente, ou podemos deixar o DataTable fazer todo o trabalho para nós e tornar a instrução mais parecida com uma chamada SQL, fazendo o seguinte:
string name = "Joe";
foreach(DataRow dr in dtPerson.Select($"name='{name}'"))
dr.Delete();
Ao chamar a Select
função de DataTable , nossa consulta evita automaticamente entradas já deletadas na DataTable. E como a Select
função retorna um array de correspondências, a coleção que estamos enumerando não é modificada quando a chamamos dr.Delete()
. Também apurei a expressão Select com interpolação de string para permitir a seleção de variáveis sem tornar o código barulhento.
[ii]
para[i]
:-)