Вопрос

Я не понимаю, почему этот код не работает.

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}
Это было полезно?

Решение

Несмотря на то DataRow.Delete не изменяет состояние коллекции, Документация Майкрософт утверждает, что вы не должны вызывать его во время итерации по коллекции:

Ни удаление, ни удаление не должны вызываться в цикле 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

возможно, мой ответ больше не будет полезен.исключение в Foreach с DataRow появляется только в .Net 2.0 и более ранних версиях, причина - описание в msdnhttp://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx

Если RowState строки имеет значение Added, строка удаляется из таблицы.

RowState становится удаленным после использования метода Delete.Он остается удаленным до тех пор, пока вы не вызовете AcceptChanges.

Удаленную строку можно восстановить, вызвав RejectChanges.

чтобы решить эту проблему, вы можете вызвать DataTable.AcceptChanges() перед использованием foreach

foreach (DataRow dataRow in dataTable.Rows)
{
    if (true)
    {
        dataRow.Delete();
    }
}

dataTable.AcceptChanges();

Пожалуйста, ознакомьтесь со снимками, чтобы понять, как это работает.

  1. Просто удалено, но не удалено из DataTable.

enter image description here

  1. Точка останова перед функцией AcceptChanges().enter image description here
  2. После выполнения функции AcceptChanges().enter image description here

Надеюсь, теперь эта проблема решена.

А 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.

Если предметы имеют 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() метод.

Использовать это:

for (int i = 0; i < myDataTable.Rows.Count; i++)

{

 myDataTable[i].Delete();

}

Это потому, что это похоже на попытку разобрать ступеньку лестницы, по которой вы поднимаетесь.Проще говоря, вы не можете удалить элемент, который выполняете итерацию.

Поэтому вам следует использовать другой массив для итерации и удаления их из таблицы данных. Rows свойство.

foreach (DataRow dataRow in dataTable.Select())
{
    if (true)
    {
        dataTable.Rows.Remove(dataRow);
    }
}

Конечно, Магенты

Вот как я это сделал и отлично работает

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++;        
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top