1

I have a DataSet dsComponents that embraces many tables, all of them are only in-memory, I don't sync them with any database. At some moments I need to remove all rows to free some memory but the function seems not to working (based on this answer)

if(dsComponents.Tables.Contains("MemoryHistory"))
{
  dsComponents.Tables["MemoryHistory"].Rows.Clear();
}

But if I break right after this code it shows that there still all rows in the table. I also tried:

if(dsComponents.Tables.Contains("MemoryHistory"))
{
  lock(dsComponents.Tables["MemoryHistory"])
  {
    foreach (DataRow row in dsComponents.Tables["MemoryHistory"].Rows)
    {
      row.Delete();
    }
  }
  dsComponents.Tables["MemoryHistory"].Rows.Clear();
}

and this one fails with "Collection was modified; enumeration operation may not execute", even with the lock. So, how to clear the rows of the table but preserve the table itself (like its Primary key, etc...)?

Fnr
  • 2,096
  • 7
  • 41
  • 76
  • `dsComponents.Tables["MemoryHistory"].Rows.Clear()` should work properly. Are you sure it's hitting that line of code and nothing else is interfering with it? – jtate Oct 01 '18 at 18:49
  • yep, at least according to VS debugger it is hitting. I also break right after to check it the rows were cleared – Fnr Oct 01 '18 at 18:50
  • 1
    you can't use a `foreach` loop and then add/remove elements to the collection inside the loop, so you could try an old fashioned `for` loop but go backwards, `for (int i = dsComponents.Tables["MemoryHistory"].Rows.Count - 1; i >= 0; i--)` and then call `dsComponents.Tables["MemoryHistory"].Rows[i].Delete()` inside the loop – jtate Oct 01 '18 at 19:01
  • @jtate this worked, thanks – Fnr Oct 01 '18 at 19:14

2 Answers2

3

The issue here is that your are modifying an Enumerable as you are iterating over it which is not allowed.

You need to reset the rows property on the table without iterating over the rows.

Think about like iterating over a List<T>

You would not do

foreach (var element in list)
{
    list.Remove(element);
}

Instead you would do something like:

list.Clear();

In your case you would want to do

dsComponents.Tables["MemoryHistory"].Rows.Clear();

I am not sure of your need for the lock object, but if you clarify that, I would be happy to modify my answer.

ninja coder
  • 1,067
  • 9
  • 22
1

Just do

dsComponents.Tables["MemoryHistory"].Clear();
DanB
  • 2,022
  • 1
  • 12
  • 24
  • this will also wipe the primary key of the table. I dont want to redefine the constraints again... – Fnr Oct 01 '18 at 18:46
  • Have you tried dsComponents.Tables["MemoryHistory"] = dsComponents.Tables["MemoryHistory"].Clone(); ? – Frank Ball Oct 01 '18 at 19:03