Подтвердить что ты не робот

Безопасное удаление DataRow In ForEach

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

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

Ответ 1

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

Ни Delete, ни Remove не должны вызываться в цикле foreach во время итерации объекта DataRowCollection. Удалить или Удалить изменить состояние коллекции.

Лучшее решение обычно состоит в том, чтобы создать отдельную коллекцию (например, List<DataRow>) элементов, которые вы хотите удалить, а затем удалить их после завершения итерации.

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

Ответ 2

Самый безопасный путь - используйте цикл for

for (int i = datatable.Rows.Count - 1; i >= 0; i--) 
{
    if (true)
    {
        datatable.Rows[i].Delete();
    }
}

Не забудьте AcceptChanges удалить все отмеченные строки:

datatable.AcceptChanges();

Ответ 3

Вы не можете изменять коллекцию во время итерации по ней с помощью инструкции 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();
}

Ответ 4

Если вы вызываете метод удаления, вам просто нужно вызвать 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

Ответ 5

может быть мой ответ более не полезен. исключение 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

Ответ 6

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

dataTable.AcceptChanges();

Обратитесь к снимкам, чтобы понять, как это работает.

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

enter image description here

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

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

Ответ 7

Содержимое Rows изменяется во время повтора, если вы удаляете одну строку, что делает итерацию недействительной.

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

Ответ 8

Самый простой способ добиться этого, используя список для сопоставления строк, которые вы хотите удалить, а затем удалите строки вне итерации 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

Ответ 9

Есть другая версия (я думаю, что проще), что я только что использовал:

int i=0;
while (i < myDataTable.Rows.Count)
{
    if (condition)  //should it be deleted?
        myDataTable.Rows.RemoveAt(i);
    else
        i++;
}

Это быстрее.

Ответ 10

Только для людей, которые ищут такой сценарий, как я, Мне нужно было сократить время, и как только какая-то полезная информация извлекается из каждой строки, я исключил строку, пометив ее как удаленную.

Надеюсь, что это поможет кому-то...

foreach (DataRow dataRow in dataTable.Rows)
{
    if (dataRow.RowState != DataRowState.Deleted)
    {
        if (your condition here)
        {
            dataRow.Delete();
        }
    }
}

Ответ 11

Это относится практически ко всей коллекции. Если вы попытаетесь удалить элемент во время цикла в коллекции, у вас возникнет проблема. Например, если вы удалите строку №3, то предыдущая строка №4 станет строкой № 3.

Ответ 12

Используйте это:

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

{

 myDataTable[i].Delete();

}

Ответ 13

Если элементы имеют 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().

Ответ 14

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

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

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

Ответ 15

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++;        
  }
}