Я не понимаю, почему этот код не работает.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
Я не понимаю, почему этот код не работает.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
Несмотря на то, что DataRow.Delete
не изменяет состояние коллекции, документация Microsoft гласит, что вы не должны вызывать ее во время итерации по коллекции:
Ни Delete, ни Remove не должны вызываться в цикле foreach во время итерации объекта DataRowCollection. Удалить или Удалить изменить состояние коллекции.
Лучшее решение обычно состоит в том, чтобы создать отдельную коллекцию (например, List<DataRow>
) элементов, которые вы хотите удалить, а затем удалить их после завершения итерации.
Это также решение для ситуаций, когда вы хотите удалить элементы из коллекции, так как большинство коллекций в .NET не позволяют вам изменять содержимое коллекции, пока вы выполняете ее.
Самый безопасный путь - используйте цикл for
for (int i = datatable.Rows.Count - 1; i >= 0; i--)
{
if (true)
{
datatable.Rows[i].Delete();
}
}
Не забудьте AcceptChanges
удалить все отмеченные строки:
datatable.AcceptChanges();
Вы не можете изменять коллекцию во время итерации по ней с помощью инструкции foreach
.
вы можете попробовать что-то вроде этого:
List<DataRow> deletedRows = new List<DataRow>();
foreach (DataRow dataRow in dataTable.Rows)
{
if(true) deletedRows.Add(dataRow);
}
foreach(DataRow dataRow in deletedRows)
{
dataRow.Delete();
}
Если вы вызываете метод удаления, вам просто нужно вызвать AcceptChanges()
в таблице, которую вы изменяете, после цикла foreach.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Метод delete просто отмечает строку для удаления.
http://msdn.microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx
может быть мой ответ более не полезен. исключение throw в Foreach с DataRow появляется только в .Net 2.0 и ранее, причина - описание в msdn http://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx
Если RowState строки добавлено, строка удаляется из таблицы.
RowState становится удаленным после использования метода Delete. Он остается удаленным, пока вы не вызываете AcceptChanges.
Удаленная строка может быть восстановлена путем вызова RejectChanges.
чтобы передать эту проблему, вы можете вызвать DataTable.AcceptChanges() перед использованием foreach
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Обратитесь к снимкам, чтобы понять, как это работает.
Я надеюсь, что эта проблема будет решена.
Содержимое Rows
изменяется во время повтора, если вы удаляете одну строку, что делает итерацию недействительной.
Вы можете, однако, скопировать строки в коллекцию сначала, а затем выполнить итерацию по коллекции и удалить строки таким образом. Это гарантирует, что итерация не прерывается путем изменения данных для повторения.
Самый простой способ добиться этого, используя список для сопоставления строк, которые вы хотите удалить, а затем удалите строки вне итерации DataTable.
С#
List<DataRow> rowsWantToDelete= new List<DataRow>();
foreach (DataRow dr in dt.Rows)
{
if(/*Your condition*/)
{
rowsWantToDelete.Add(dr);
}
}
foreach(DataRow dr in rowsWantToDelete)
{
dt.Rows.Remove(dr);
}
В. Б.
Dim rowsWantToDelete As New List(Of DataRow)
For Each dr As DataRow In dt
If 'Your condition' Then
rowsWantToDelete .Add(dr)
End If
Next
For Each dr As DataRow In rowsWantToDelete
dt.Rows.Remove(dr)
Next
Есть другая версия (я думаю, что проще), что я только что использовал:
int i=0;
while (i < myDataTable.Rows.Count)
{
if (condition) //should it be deleted?
myDataTable.Rows.RemoveAt(i);
else
i++;
}
Это быстрее.
Только для людей, которые ищут такой сценарий, как я, Мне нужно было сократить время, и как только какая-то полезная информация извлекается из каждой строки, я исключил строку, пометив ее как удаленную.
Надеюсь, что это поможет кому-то...
foreach (DataRow dataRow in dataTable.Rows)
{
if (dataRow.RowState != DataRowState.Deleted)
{
if (your condition here)
{
dataRow.Delete();
}
}
}
Это относится практически ко всей коллекции. Если вы попытаетесь удалить элемент во время цикла в коллекции, у вас возникнет проблема. Например, если вы удалите строку №3, то предыдущая строка №4 станет строкой № 3.
Используйте это:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
Если элементы имеют Count
, это то, что я сделал:
int Count = myTable.Rows.Count;
while (Count > 0) // replace condition with myTable.Rows.Count if unconditionally performed on all rows
{
DataRow row = myTable.Rows[0] // or however you want to find your index
// do some work
myTable.Rows.Remove(row);
// if you want to perform a check to break out of while
if (someCondition)
Count = 0;
else
Count = myTable.Rows.Count;
}
Обратите внимание, что если объекты имеют коллекцию .GetXXXX()
, например FileInfo
(IIRC),
удаление содержимого элемента в foreach
является приемлемым. Одним из решений, которое я рассмотрел, является создание метода расширения, который предоставляет метод .GetItems()
.
Это потому, что похоже на попытку разобрать лестницу лестницы, которую вы поднимаете. Просто вы не можете удалить элемент, который вы итерации.
Поэтому вы должны использовать другой массив для итерации и удалить их из свойства datatable Rows
.
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
Sure Magents
Вот как я это сделал и прекрасно работает
dt = GetStationeryConsolidationDetails(txtRefNo.Text);
int intRows = dt.Rows.Count;
int x = 0;
for (int c = 0; c < intRows; c++)
{
if (dt.Rows[c - x]["DQTY"].ToString() == "0")
{
dt.Rows[c - x].Delete();
dt.AcceptChanges();
x++;
}
}