1132 votes

Requête LINQ sur une DataTable

J'essaie d'effectuer une requête LINQ sur un objet DataTable et, bizarrement, je constate que l'exécution de telles requêtes sur des DataTables n'est pas simple. Par exemple :

var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;

Ceci n'est pas autorisé. Comment faire pour que quelque chose comme ça fonctionne ?

Je suis étonné que les requêtes LINQ ne soient pas autorisées sur les DataTables !

3 votes

Vous pouvez trouver d'autres exemples de LINQ/Lambda à l'adresse suivante webmingle.blogspot.com/2010_09_01_archive.html

0 votes

C'est parce que les tables de données ont précédé LINQ d'un certain nombre d'années. Utilisez plutôt une table de données fortement typée ; c'est une meilleure expérience que cette méthode de typage stricte, qui nuit à l'intellisense. dt.Rows["FirstName] junk Avec une table fortement typée (ajoutez un fichier de type DataSet à votre projet et créez des tables à l'intérieur de celui-ci dans le concepteur visuel), il vous suffit d'écrire par ex. myStronglyTpedDataset.Person.Where(p => p.FirstName == "John") - toute la magie pour que cela arrive est déjà faite.

0 votes

@CaiusJard cela signifie-t-il que vous devriez créer un fichier de type DataSet pour chaque requête ?

1396voto

Collin K Points 6535

Vous ne pouvez pas effectuer de requête contre le DataTable 's Rangs puisque DataRowCollection ne met pas en œuvre IEnumerable<T> . Vous devez utiliser le AsEnumerable() extension pour DataTable . Comme ça :

var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;

Et comme @Keith dit, vous devrez ajouter une référence à System.Data.DataSetExtensions

AsEnumerable() renvoie à IEnumerable<DataRow> . Si vous devez convertir IEnumerable<DataRow> à un DataTable utilisez le CopyToDataTable() extension.

Voici une requête avec une expression lambda,

var result = myDataTable
    .AsEnumerable()
    .Where(myRow => myRow.Field<int>("RowNo") == 1);

8 votes

Version VB : Dim results = From myRow In myDataTable.AsEnumerable _ Where myRow.Field("RowNo") = 1 _ Select myRow

17 votes

J'avais déjà une référence à la dll mentionnée, mais il me manquait using System.Data;

3 votes

Comment récupérer une DataTable à partir de var results ?

141voto

JoelFan Points 11368
var results = from DataRow myRow in myDataTable.Rows
    where (int)myRow["RowNo"] == 1
    select myRow

2 votes

Qu'en est-il de la sélection de plusieurs lignes, au lieu de la seule ligne 1 ?

2 votes

Enlevez simplement la ligne "where" et vous obtiendrez toutes les lignes.

2 votes

Oui, c'est comme ça que j'ai l'habitude de faire, sauf qu'il faut remplacer (int)myRow["RowNo"] avec la forme générique myRow.Field<int>("RowNo") pour prendre en charge de manière plus pratique les types nullables.

75voto

Jon Limjap Points 46429

Ce n'est pas qu'ils étaient délibérément interdits sur les DataTables, c'est juste que les DataTables sont antérieurs aux constructions IQueryable et IEnumerable génériques sur lesquelles les requêtes Linq peuvent être effectuées.

Les deux interfaces nécessitent une sorte de validation de la sécurité des types. Les DataTables ne sont pas fortement typées. C'est la même raison pour laquelle les gens ne peuvent pas effectuer de requêtes sur une ArrayList, par exemple.

Pour que Linq fonctionne, vous devez mapper vos résultats sur des objets de type sûr et effectuer des requêtes sur ces objets.

54voto

Keith Points 46288

Comme l'a dit @ch00k :

using System.Data; //needed for the extension methods to work

...

var results = 
    from myRow in myDataTable.Rows 
    where myRow.Field<int>("RowNo") == 1 
    select myRow; //select the thing you want, not the collection

Vous devez également ajouter une référence de projet à System.Data.DataSetExtensions

1 votes

Si vous essayez, vous verrez que cela ne fonctionnera pas à moins de mettre un type spécifique sur myRow ou utiliser Cast<DataRow>() sur Rows . Mieux vaut utiliser AsEnumerable() .

1 votes

@NetMage ça a marché il y a 12 ans quand je l'ai posté. Tant que vous avez System.Linq y System.Data.DataSetExtensions puis myDataTable.Rows renvoie une collection énumérable de DataRow de toute façon. Ça a peut-être changé, ça fait une décennie que je ne l'ai pas utilisé.

1 votes

Intéressant - Je suppose qu'il a été modifié à un moment donné, puisqu'il ne fonctionne pas sur .Net ou .Net Core maintenant.

40voto

Ravi Points 161
var query = from p in dt.AsEnumerable()
                    where p.Field<string>("code") == this.txtCat.Text
                    select new
                    {
                        name = p.Field<string>("name"),
                        age= p.Field<int>("age")                         
                    };

les champs nom et âge font maintenant partie de l'objet de la requête et on peut y accéder comme suit : Console.WriteLine(query.name) ;

1 votes

Comment j'utilise mon nom ? Par exemple, MessageBox.Show(name) est indéfinie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X