0
private DataTable InsertABlankRow(DataTable dt)
    {
        int n = dt.Rows.Count;
        DataTable dtnew = new DataTable();
        if (dt.Columns.Contains("colname"))
        {
            var countRows = dt.Select("colname ='xyz'").Length;

            if (countRows > 1)
            {
                foreach (DataRow drow in dt.Rows)
                {
                    if (drow["colname"].ToString() == "xyz")
                    {
                        int index = dt.Rows.IndexOf(drow);
                        dt.Rows.InsertAt(dt.NewRow(), index + 1); 
                        dt.AcceptChanges();
                    }
                }
            }
        }
}

Modified code:

private DataTable Add_a_Row(DataTable dtnew)
    {
       DataTable dt = new DataTable();
        dt= dtnew.Clone();
        foreach (DataRow dr in dtnew.Rows)
        {
            dt.ImportRow(dr);
            if(dr["colname"].ToString()=="xyz")
            {
               dt.Rows.Add(dt.NewRow());
            }
        }
        return dt;
    }

Hi All, I am trying to insert blank rows at multiple places where ever the condition is met. For the first time when the condition is met a new empty row is added but for the second one it throws an exception, collection changed. Is there a way to do this in a much better way. Thank you...

Skanda
  • 131
  • 4
  • 14
  • I think after you insert row at specific index using InsertAt method you should call AcceptChanges method. dt.AcceptChanges() – Bhuban Shrestha Jun 27 '17 at 17:40
  • I am doing that, might not show in the code but it still throws the error even after adding that. – Skanda Jun 27 '17 at 17:42
  • You cannot modify a collection that you are enumerating. The foreach is getting screwed up because the original collection it started with has changed now. – Varun Mehta Jun 27 '17 at 17:44
  • Yeah I saw the problem you are looping through dt datatable and you are adding row to the same dt. So after dt change loop will throw error instead you should copy dt to another variable say dt1 loop through dt1 and add row in dt. – Bhuban Shrestha Jun 27 '17 at 17:45
  • Use `for` loop instead of `foreach` – Crowcoder Jun 27 '17 at 17:47
  • https://stackoverflow.com/questions/16497028/how-add-or-remove-object-while-iterating-collection-in-c-sharp – Slai Jun 27 '17 at 19:24

4 Answers4

1

You cannot modify the same collection you are looping through.The collection in foreach should be immutable.

Inside foreach (DataRow drow in dt.Rows) ,You should not change dt.Rows.InsertAt. This breaks the for each, say you are looping through the second item,now you are inserting another row at 2nd and 2nd row moved to 3rd.Now you are again looping through 2nd.

Refer this SO post or this for more

Rohith
  • 5,527
  • 3
  • 27
  • 31
  • I modified my code as shown above, but again I get issues of index of the row being chaged. Any pointers on this. – Skanda Jun 27 '17 at 18:29
  • I actually got the answer myself, it works as shown above. Thank you all for your inputs. – Skanda Jun 27 '17 at 18:38
0

Every time you add a row, the row collection in for-loop condition changes, thus you are getting that particular error. You should try something recursive like this:

    void AddRowInDatatable(Datatable dt)
   {
      foreach (DataRow drow in dt.Rows)
            {
                if (drow["colname"].ToString() == "xyz")
                {
                    int index = dt.Rows.IndexOf(drow);
                    dt.Rows.InsertAt(dt.NewRow(), index + 1);
                    AddRowInDatatable(dt);
                }
            }
    }

use this method replacing your for-loop. As @Bhuban pointed out, it might be an infinite loop, but you might get the idea. modify the code further as i haven't tested it, just wrote it out of my mind

boop_the_snoot
  • 3,209
  • 4
  • 33
  • 44
0
private DataTable InsertABlankRow(DataTable dt)
{
   int n = dt.Rows.Count;
   DataTable dtnew = dt.Copy();
   if (dt.Columns.Contains("colname"))
   {
     var countRows = dt.Select("colname ='xyz'").Length;
     if (countRows > 1)
     {
      for(int i =0; i< dtnew.Rows.Count; i++)
       {
        if (dtnew.Rows[i]["colname"].ToString() == "xyz")
         {
          dt.Rows.InsertAt(dt.NewRow(), i+1);              
         }
        }
       dt.AcceptChanges();
      }
   }
return dt;
}

Basically I have made copy of passed data table and stored in new datatable called dtnew. Loop through each row of dtnew datatable using for because with this i get variable value with which index can be supplied and inserted new row to original data table.

Bhuban Shrestha
  • 1,304
  • 11
  • 27
0

This is a common problem of removing or inserting items from a collection while enumerating it.

  1. The usual solution is to index the collection in reverse order:

    for (int i = list1.Count - 1; i >= 0; i--)
        list1.RemoveAt(i);
    
  2. Another solution is to create another collection:

    foreach (var item in list1)
        list2.Add(item);
    
  3. The easiest and usually the least efficient solution is to enumerate a copy of the collection:

    foreach (var item in list1.ToList())
        list1.Remove(item);
    
Slai
  • 22,144
  • 5
  • 45
  • 53