web-dev-qa-db-fra.com

DataTable, Comment supprimer conditionnellement des lignes

Je suis engagé dans un processus d'apprentissage C # et ça se passe bien jusqu'à présent. Cependant, je viens de frapper mon premier "dis quoi?" moment.

Le DataTable offre un accès aléatoire aux lignes à sa collection de lignes, non seulement via le comportement des collections typiques, mais aussi via DataTable.Select. Cependant, je n'arrive pas à lier cette capacité à DataRow.Delete. Jusqu'à présent, c'est ce qu'il semble que je dois faire pour supprimer conditionnellement une ou plusieurs lignes d'une table.

int max = someDataTable.Rows.Count - 1;
for(int i = max; i >= 0; --i)
{
    if((int)someDataTable.Rows[i].ItemArray[0] == someValue)
    {
        someDataTable.Rows[i].BeginEdit();
        someDataTable.Rows[i].Delete();
    }
    else
        break;
}
someDataTable.AcceptChanges();

Mais je ne suis pas satisfait de ce code. Je ne suis pas non plus convaincu. J'ai dû louper quelque chose. Suis-je vraiment obligé de frapper la collection Rows de manière séquentielle si je dois supprimer une ou plusieurs lignes de manière conditionnelle?

(ne me dérange pas l'inversé pour. Je supprime de la fin du datatable. Donc c'est ok)

36
Alexandre Bell

Vous pouvez interroger l'ensemble de données, puis boucler les lignes sélectionnées pour les définir comme supprimées.

var rows = dt.Select("col1 > 5");
foreach (var row in rows)
    row.Delete();

... et vous pouvez également créer des méthodes d'extension pour le rendre plus facile ...

myTable.Delete("col1 > 5");

public static DataTable Delete(this DataTable table, string filter)
{
    table.Select(filter).Delete();
    return table;
}
public static void Delete(this IEnumerable<DataRow> rows)
{
    foreach (var row in rows)
        row.Delete();
}
69
Matthew Whited

Voici une ligne unique utilisant LINQ et évitant toute évaluation au moment de l'exécution de certaines chaînes:

someDataTable.Rows.Cast<DataRow>().Where(
    r => r.ItemArray[0] == someValue).ToList().ForEach(r => r.Delete());
37
Alain

Je n'ai pas de boîte Windows à portée de main pour essayer cela, mais je pense que vous pouvez utiliser un DataView et faire quelque chose comme ça:

DataView view = new DataView(ds.Tables["MyTable"]);
view.RowFilter = "MyValue = 42"; // MyValue here is a column name

// Delete these rows.
foreach (DataRowView row in view)
{
  row.Delete();
}

Je n'ai cependant pas testé cela. Vous pourriez essayer.

8
itsmatt

Méthode d'extension basée sur Linq

public static void DeleteRows(this DataTable dt, Func<DataRow, bool> predicate)
{
    foreach (var row in dt.Rows.Cast<DataRow>().Where(predicate).ToList())
        row.Delete();
}

Utilisez ensuite:

DataTable dt = GetSomeData();
dt.DeleteRows(r => r.Field<double>("Amount") > 123.12 && r.Field<string>("ABC") == "XYZ");
0
Sebastian Widz