Rimozione sicura DataRow In PerOgni
-
22-09-2019 - |
Domanda
Non capisco perché questo codice non funziona.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
Soluzione
Anche se DataRow.Delete
non modifica lo stato della raccolta, documentazione di Microsoft afferma che non si deve chiamare, mentre l'iterazione sulla raccolta:
Né Elimina né Rimuovere dovrebbe essere chiamato in un ciclo foreach, mentre l'iterazione attraverso un oggetto DataRowCollection. Eliminare né Rimuovere modificare lo stato della collezione.
La soluzione migliore è di solito per creare una raccolta differenziata (per esempio un List<DataRow>
) di elementi che si desidera rimuovere, quindi rimuoverli dopo si iterazione hai finito.
Questa è anche la soluzione per le situazioni in cui si desidera rimuovere elementi da una collezione, come la maggior parte raccolte in .NET non consentono di modificare i contenuti della collezione, mentre si sta iterando su di esso.
Altri suggerimenti
modo più sicuro - uso ciclo for
for (int i = datatable.Rows.Count - 1; i >= 0; i--)
{
if (true)
{
datatable.Rows[i].Delete();
}
}
Non dimenticare di AcceptChanges
per rimuovere tutte le righe marcate:
datatable.AcceptChanges();
Non è possibile modificare una raccolta, mentre si sta iterando su di esso utilizzando una dichiarazione foreach
.
si può provare qualcosa di simile:
List<DataRow> deletedRows = new List<DataRow>();
foreach (DataRow dataRow in dataTable.Rows)
{
if(true) deletedRows.Add(dataRow);
}
foreach(DataRow dataRow in deletedRows)
{
dataRow.Delete();
}
Se si chiama il metodo di eliminazione è sufficiente chiamare AcceptChanges()
sul tavolo si sta modificando, dopo il ciclo foreach.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Il metodo delete segna semplicemente la fila per l'eliminazione.
http: //msdn.microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx
può essere la mia risposta non è più utile. eccezione tiro in Foreach con DataRow appaiono solo in .Net 2.0 e versioni precedenti, la ragione è la descrizione a MSDN http: // MSDN. microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx
Se la RowState della riga viene aggiunta, la riga viene rimossa dalla tabella.
Il RowState viene eliminato dopo aver utilizzato il metodo Delete. Rimane eliminati fino a quando si chiama AcceptChanges.
Una riga eliminata può essere eliminate invocando RejectChanges.
per passare questo problema è possibile chiamare DataTable.AcceptChanges () prima di utilizzare foreach
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Si prega di fare riferimento gli snap per understatnd il funzionamento di esso.
- appena cancellato, ma non rimosso dal DataTable.
- Punto di rottura prima AcceptChanges () Funzione.
- Dopo Eexecuting AcceptChanges () Funzione.
Spero che questo problema è stato risolto ora.
Le modifiche al contenuto Rows
mentre si è l'iterazione se si elimina una riga, che rende l'iterazione valido.
È possibile, tuttavia, copiare le righe in una collezione e poi iterare la raccolta e cancellare le righe in questo modo. Questo fa in modo che l'iterazione non è interrotto modificando dati da iterata.
Il modo più semplice per raggiungere questo obiettivo utilizzando un elenco per mappare le righe che si desidera eliminare e quindi eliminare le righe al di fuori iterazione DataTable.
C #
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);
}
VB
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
C'è un'altra versione di esso (credo uno più facile) quello che ho appena usato:
int i=0;
while (i < myDataTable.Rows.Count)
{
if (condition) //should it be deleted?
myDataTable.Rows.RemoveAt(i);
else
i++;
}
Questa veloce.
Solo per le persone che sono alla ricerca di scenario specifico, come me, Ho bisogno di abbreviare tempo impiegato, e una volta alcuni infomation utile viene estratto da ciascuna riga, ho escluso la riga contrassegnando come cancellata.
Spero che questo aiuto a qualcuno ...
foreach (DataRow dataRow in dataTable.Rows)
{
if (dataRow.RowState != DataRowState.Deleted)
{
if (your condition here)
{
dataRow.Delete();
}
}
}
Questo vale per praticamente qualsiasi collezione. Se si tenta di eliminare un elemento, mentre scorrendo la raccolta, si avrà un problema. Ad esempio, se si elimina riga # 3, quindi la precedente riga # 4 diventa riga # 3.
Quando gli oggetti hanno un Count
, questo è quello che ho fatto:
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;
}
Si noti che dove gli oggetti hanno una collezione .GetXXXX()
, come FileInfo
(IIRC),
cancellazione del contenuto della voce in una foreach
è accettabile. Una soluzione che ho considerato è creare un metodo di estensione che fornisce un metodo .GetItems()
.
Utilizzare questa:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
Questo è perché sembra tentare di smontare la scala di scala che si sale. Semplicemente, non è possibile rimuovere un elemento di eseguire iterazioni.
Per questo è necessario utilizzare array diverso per scorrere e rimuoverli dalla proprietà Rows
DataTable.
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
Certo magenti
Ecco come ho fatto e funziona benissimo
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++;
}
}