Error in datarow, collection has been changed; enumeration operation may not be performed

I have for each cycle in which the data row is updated, so the exception has been changed; An enumeration operation has been generated. any way to fix it? I saw the To-List function, but it does not work with a data row, here is my code:

foreach (DataRow row in dataTable.Rows) { temp = row[0].ToString(); foreach (DataRow rows in dataTable.Rows) { if (temp == rows[0].ToString()) { tempdatatable.Rows.Add(row[0],row[1]); dataTable.Rows.Remove(rows); //Update happens here } tempdatatable.DefaultView.Sort = "gscitations DESC"; dataGridView1.DataSource = tempdatatable; } } 
+4
source share
3 answers

Try the following:

 for (int i = 0; i < dataTable.Rows.Count; i++) { var tempRow = dataTable.Rows[i]; var temp = dataTable.Rows[i][0]; for (int j = 0; j < dataTable.Rows.Count; j++) { DataRow rows = dataTable.Rows[j]; if (temp == rows[0].ToString()) { tempdatatable.Rows.Add(tempRow[0], tempRow[1]); dataTable.Rows.Remove(rows); //Update happen here } tempdatatable.DefaultView.Sort = "gscitations DESC"; dataGridView1.DataSource = tempdatatable; } } 
+3
source

You cannot modify a collection when enumerating it with the Enumerator, which happens behind the scene of the foreach ( MDSN link ).

One of the possible ways to solve this problem is to collect the lines that will be deleted in the first listing, and delete them in a separate loop as follows:

 var rowsToDelete = new List<DataRow>(); foreach (DataRow row in dataTable.Rows) { temp = row[0].ToString(); foreach (DataRow rows in dataTable.Rows) { if (temp == rows[0].ToString()) { tempdatatable.Rows.Add(row[0],row[1]); rowsToDelete.Add(rows); } tempdatatable.DefaultView.Sort = "gscitations DESC"; dataGridView1.DataSource = tempdatatable; } } rowsToDelete.ForEach( x => dataTable.Rows.Remove(x) ); 

You can also replace the foreach with for , but you need to do some extra work by correctly processing the current index when deleting items.

+5
source

I would say that you should make a separate table of records, and instead of calling datatable.Rows.Remove (rows) add the row "rows" to this other table. Then, when the lines or lines of iteration are executed, you run the if statement to check if it has been "deleted", i.e. In the list of deleted rows. After the listing ends, you can delete these rows from the table.

EDIT:

Here's the code implementation:

 DataTable duplicates = dataTable; duplicates.Rows.Clear(); /* Produces an empty duplicate of the dataTable table to put the duplicates in */ foreach (DataRow row in dataTable.Rows) { if (!duplicates.Rows.Contains(row)) { temp = row[0].ToString(); foreach (DataRow rows in dataTable.Rows) { if (temp == rows[0].ToString()&&!duplicates.Rows.Contains(rows)) //need unique key { tempdatatable.Rows.Add(row[0],row[1]); } tempdatatable.DefaultView.Sort = "gscitations DESC"; dataGridView1.DataSource = tempdatatable; } } } foreach (DataRow row in duplicates.Rows) { dataTable.Rows.Remove(row); } 

if you don’t have a unique key, you can try switching !duplicates.Rows.Contains(/*specific row*/) to duplicates.Rows.IndexOf(/*specific row*/)>0 . This should provide an adequate replacement.

-1
source

All Articles