Как удалить DataColumn из DataTable программно
У меня есть код
foreach (DataColumn dataTableCol in this.dataTable.Columns)
{
bool columnFound = false;
foreach (GRTColumnView uiColumn in descriptor.UIColumns)
{
if (dataTableCol.ColumnName.Equals(uiColumn.Name))
{
columnFound = true;
break;
}
}
if (!columnFound)
{
if (this.dataTable.Columns.Contains(dataTableCol.ColumnName))
this.dataTable.Columns.Remove(dataTableCol.ColumnName);
}
}
Я хочу удалить некоторые "вещи" из коллекции, если они не найдены в другой коллекции.
Когда я запускаю вышеуказанную программу, я получаю
Итерация может не выполняться, так как коллекция была изменена
"Коллекция была изменена" - потому что удаление должно быть ударил
Как можно достичь такой цели?
Что я могу придумать, так это записать все "вещи", которые нужно удалить, а затем
foreach( aThing in all_things_to_remove)
remove_from_collection(aThing)
Но вышеупомянутое не кажется мне хорошим способом, так как я должен сделать еще один цикл и использую дополнительную память
3 ответа
В этом конкретном случае, когда вы просматриваете небольшую коллекцию, содержащую несколько столбцов, вы можете просто создать новую коллекцию (через ToList()
), так что вы не перебираете ту же коллекцию, которую модифицируете:
foreach (var dataTableCol in dataTable.Columns.Cast<DataColumn>().ToList())
{
...
dataTable.Columns.Remove(dataTableCol.ColumnName);
}
Рекомендуемый способ, особенно если коллекция большая, состоит в перечислении в обратном порядке:
for (var i = dataTable.Columns.Count - 1; i >= 0; i--)
{
...
dataTable.Columns.Remove(dataTable.Columns[i].ColumnName);
}
if (dt.Columns.Contains("RecordID")){
dt.Columns.Remove("RecordID");
dt.AcceptChanges();
}
Вы не можете удалять элементы из коллекции, перечисляя ее с помощью цикла foreach. Сделайте копию коллекции, используя Collection.ToArray()
и запустить вас foreach на копию и удалить свой элемент из фактической коллекции.
Поскольку DataTable.Columns не имеет ToArray
или же ToList
методы, вы могли бы использовать CopyTo()
метод и скопировать все столбцы в ColumnsArray.
Если вы не хотите создавать копию, вы можете использовать цикл for вместо цикла foreach. Вы можете редактировать свой код следующим образом:
for (int i = 0; i < dataTable.Columns.Count; i++)
{
bool columnFound = false;
foreach (GRTColumnView uiColumn in descriptor.UIColumns)
{
if (dataTable.Columns[i].Name.Equals(uiColumn.Name))
{
columnFound = true;
break;
}
}
if (!columnFound)
{
if (this.dataTable.Columns.Contains(dataTableCol.ColumnName))
this.dataTable.Columns.Remove(dataTableCol.ColumnName);
}
}
Другой способ - понижение индекса после удаления столбца.
for (int i = 0; i < datatable.Columns.Count; i++)
{
if (datatable.Columns[i].ColumnName.Contains("Column"))
{
datatable.Columns.RemoveAt(i);
i--;
}
}