1

I want to remove all empty columns from a DataTable. I created a list of all columns that consist of only empty rows, and then delete them.

It doesn't work because of a System.InvalidOperationException. The exception claims I try to edit the collection that I enumerate, something I don't understand since I think I copied that collection.

private DataTable data;

public void removeEmptyColoums()
{
// Get all empty coloums
  IEnumerable<DataColumn> queriableColumms = data.Columns.Cast<DataColumn>().AsQueryable();
  var toBeRemoved = from DataColumn column in queriableColumms
                    where data.AsEnumerable().All(row => row.IsNull(column))
                    select column;
  // Delete them
  foreach(DataColumn column in toBeRemoved)  // Exception thrown here
  {
    data.Columns.Remove(column);
  }
}

I'm not sure about the. AsQueryable and .Cast calls either.

3
  • When you remove items fro a list you have to start at last item and work towards beginning. For example if you have rows 1,2,3 and you remove row 2 then row 3 becomes 2. Well your exception was due to same issue. Try following : for(int i = toBeRemoved.Count() - 1; i >= 0; i-- ) { _data.Columns.Remove(toBeRemoved.Skip(i).First()); } Commented Jun 23, 2017 at 14:56
  • foreach(DataColumn column in toBeRemoved.ToArray() Commented Jun 23, 2017 at 14:57
  • define it like an array var[] toBeRemoved and then perform iteration of foreach loop on it Commented Jun 23, 2017 at 15:11

1 Answer 1

1

My humble guess:

As long as the list isn't finalized (with ToList() for example), you are indeed working on it, and never actually making a copy.

IEnumerable<DataColumn> queriableColumms = data.Columns.Cast<DataColumn>().AsQueryable();

We see here that you use data to produce a Queryable, not an independent list.

var toBeRemoved = from DataColumn column in queriableColumms
                where data.AsEnumerable().All(row => row.IsNull(column))
                select column;

Here as well, you're using LinqToSQL, and not finalizing the list.

So when you call toBeRemoved, you call the query's result, thus are still using the original source, data.

Try using toBeRemoved.ToList(), and doing your loop on that.


Actually, I think the problem may lie somewhere else since you say your exception happens when you start your loop on toBeRemoved and not when you actually try to delete an item, but I'll edit later if this solution doesn't work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.