En toute sécurité Retrait DataRow dans le foreach
-
22-09-2019 - |
Question
Je ne comprends pas pourquoi ce code ne fonctionne pas.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
La solution
Même si DataRow.Delete
ne modifie pas l'état de la collection, documentation Microsoft indique que vous ne devriez pas l'appeler en itérer sur la collection:
Ni Supprimer ni les supprimer doit être appelé dans une boucle foreach tout itérer un objet DataRowCollection. Supprimer ni supprimer modifier l'état de la collection.
La meilleure solution est généralement de créer une collection séparée (par exemple un List<DataRow>
) d'articles que vous voulez supprimer, puis les enlever après vous avez terminé itérer.
Ceci est également la solution pour les situations où vous voulez supprimer des éléments d'une collection, comme la plupart des collections .NET ne vous permettent pas de modifier le contenu de la collection pendant que nous parcourons dessus.
Autres conseils
plus sûr - l'utilisation de la boucle for
for (int i = datatable.Rows.Count - 1; i >= 0; i--)
{
if (true)
{
datatable.Rows[i].Delete();
}
}
Ne pas oublier de AcceptChanges
pour supprimer toutes les lignes marquées:
datatable.AcceptChanges();
Vous ne pouvez pas modifier une collection alors que nous parcourons à ce sujet en utilisant une instruction foreach
.
vous pouvez essayer quelque chose comme ça:
List<DataRow> deletedRows = new List<DataRow>();
foreach (DataRow dataRow in dataTable.Rows)
{
if(true) deletedRows.Add(dataRow);
}
foreach(DataRow dataRow in deletedRows)
{
dataRow.Delete();
}
Si vous appelez la méthode de suppression vous suffit d'appeler AcceptChanges()
sur la table que vous modifiez, après la boucle foreach.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
La méthode de suppression marque simplement la ligne pour la suppression.
http: //msdn.microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx
peut-être ma réponse ne sont plus utiles. jet d'exception dans le foreach avec DataRow apparaissent uniquement dans .Net 2.0 et plus tôt, la raison est la description à msdn http: // msdn. microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx
Si la RowState de la ligne est ajoutée, la ligne est retirée de la table.
Le RowState devient supprimé après avoir utilisé la méthode Delete. Il reste supprimé jusqu'à ce que vous appelez AcceptChanges.
Une ligne supprimée peuvent être rétablies en invoquant RejectChanges.
pour passer ce problème, vous pouvez appeler DataTable.AcceptChanges () avant d'utiliser foreach
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
S'il vous plaît Reportez-vous les boutons-pression à understatnd le fonctionnement de celui-ci.
- Juste supprimé, mais pas retiré du DataTable.
- point de rupture avant AcceptChanges () Fonction.
- Après Eexecuting AcceptChanges () Fonction.
J'espère que ce problème résolu maintenant.
Les changements de contenu Rows
pendant que vous itérez si vous supprimez une ligne, ce qui rend l'itération non valide.
Vous pouvez cependant copier les lignes dans une collection première et itérer puis sur la collecte et supprimer les lignes de cette façon. Cela fait en sorte que l'itération ne soit pas interrompue en changeant les données à itéré.
La meilleure façon d'y parvenir en utilisant une liste carte lignes que vous souhaitez supprimer, puis supprimer des lignes en dehors itération 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
Il y a une autre version (je pense un plus facile) ce que je viens d'utiliser:
int i=0;
while (i < myDataTable.Rows.Count)
{
if (condition) //should it be deleted?
myDataTable.Rows.RemoveAt(i);
else
i++;
}
Cette plus rapide.
Seulement pour les personnes qui sont à la recherche pour le scénario spécifique comme moi, Je besoin de raccourcir le temps de prise, et une fois que certains infomation utile est extrait de chaque rangée, la rangée I exclu par le marquage comme supprimé.
Hope this quelqu'un aide ...
foreach (DataRow dataRow in dataTable.Rows)
{
if (dataRow.RowState != DataRowState.Deleted)
{
if (your condition here)
{
dataRow.Delete();
}
}
}
Cela vaut pour à peu près toute collection. Si vous essayez de supprimer un élément en boucle à travers la collection, vous aurez un problème. Par exemple, si vous supprimez la ligne n ° 3, puis la ligne précédente # 4 est la ligne n ° 3.
Lorsque des éléments ont une Count
, voici ce que je l'ai fait:
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;
}
Notez que lorsque les objets ont une collection de .GetXXXX()
, comme FileInfo
(IIRC),
la suppression du contenu de l'élément dans un foreach
est acceptable. Une solution que je l'ai considéré est la création d'une méthode d'extension qui fournit une méthode de .GetItems()
.
Utilisez ceci:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
Ceci est parce qu'il ressemble à essayer de démonter l'escalier d'escalier que vous montez. Simplement, vous ne pouvez pas supprimer un élément que vous itérer.
Par conséquent, vous devez utiliser le tableau différent pour itérer et les retirer de la propriété DataTable Rows
.
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
Bien sûr magents
Voici comment je l'ai fait et fonctionne très bien
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++;
}
}