Je ne comprends pas pourquoi ce code ne fonctionne pas.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
La plupart des collections dans .NET ne vous permettent pas de modifier le contenu de la collection pendant que vous parcourez celle-ci. À partir de docs pour IEnumerator
:
Un énumérateur reste valable aussi longtemps que la collection reste inchangée. Si des modifications sont apportées à la collection, comme l'ajout, la modification ou la suppression de éléments, l'énumérateur est irrécupérablement invalidé et le prochain appel à MoveNext ou Reset lance un InvalidOperationException. Si la la collection est modifiée entre MoveNext et Current, Retours actuels l'élément sur lequel il est défini, même si l'énumérateur est déjà invalidé.
La meilleure solution consiste généralement à créer une collection distincte (par exemple, un List<DataRow>
) d'éléments à supprimer, puis à les supprimer après que vous avez terminé d'itérer.
Le moyen le plus sûr - utilisez la boucle for
for (int i = datatable.Rows.Count - 1; i >= 0; i--)
{
if (true)
{
datatable.Rows[i].Delete();
}
}
N'oubliez pas de AcceptChanges
pour supprimer toutes les lignes marquées:
datatable.AcceptChanges();
Vous ne pouvez pas modifier une collection pendant une itération à l'aide d'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 delete, vous devez simplement 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 delete marque simplement la ligne à supprimer.
http://msdn.Microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx
peut-être ma réponse ne sera-t-elle plus utile… ... exception jeter dans Foreach avec DataRow n'apparaît que dans .Net 2.0 et versions antérieures, la raison en est la description dans msdn http://msdn.Microsoft.com/en-us /library/system.data.datarow.delete(v=vs.80).aspx
Si RowState de la ligne est Added, la ligne est supprimée du tableau.
RowState devient Deleted après avoir utilisé la méthode Delete. Il reste supprimé jusqu'à ce que vous appeliez AcceptChanges.
Une ligne supprimée peut être annulée en appelant RejectChanges.
pour résoudre 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 se référer les clichés pour comprendre le fonctionnement de celui-ci.
J'espère que ce problème est résolu maintenant.
Il existe une autre version de ce que je viens d’utiliser (je pense être plus facile):
int i=0;
while (i < myDataTable.Rows.Count)
{
if (condition) //should it be deleted?
myDataTable.Rows.RemoveAt(i);
else
i++;
}
Ce plus vite.
Seulement pour les personnes qui recherchent un scénario spécifique comme moi, Je devais raccourcir le temps pris, et une fois que des informations utiles étaient extraites de chaque ligne, j’excluais la ligne en la marquant comme étant supprimé.
J'espère que cela aidera quelqu'un ...
foreach (DataRow dataRow in dataTable.Rows)
{
if (dataRow.RowState != DataRowState.Deleted)
{
if (your condition here)
{
dataRow.Delete();
}
}
}
Le moyen le plus simple d'y parvenir consiste à utiliser une liste pour mapper les lignes que vous souhaitez supprimer, puis supprimer des lignes en dehors de l'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
Le contenu Rows
change pendant l'itération si vous supprimez une ligne, ce qui rend l'itération non valide.
Cependant, vous pouvez d'abord copier les lignes dans une collection, puis parcourir la collection et supprimer les lignes de cette façon. Cela garantit que l'itération n'est pas interrompue par la modification des données à itérer.
C’est parce qu’il semble que vous essayez de démonter l’escalier que vous montez. Simplement, vous ne pouvez pas supprimer un élément que vous parcourez.
Par conséquent, vous devez utiliser un tableau différent pour itérer et les supprimer de la propriété datatable Rows
.
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
Lorsque les éléments ont une Count
, voici ce que j'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 .GetXXXX()
, telle que FileInfo
(IIRC), .__, la suppression du contenu de l’élément dans foreach
est acceptable. Une solution que j'ai envisagée est la création d'une méthode d'extension qui fournit une méthode .GetItems()
.
Bien sûr Magents
Voici comment je l'ai fait et fonctionne 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++;
}
}
Utilisez ceci:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
Cela s'applique à peu près à n'importe quelle collection. Si vous essayez de supprimer un élément en parcourant la collection, vous aurez un problème. Par exemple, si vous supprimez la ligne 3, la ligne précédente 4 devient la ligne 3.