J'essaie d'effectuer une requête LINQ sur un objet DataTable et bizarrement, je trouve que l'exécution de telles requêtes sur DataTables n'est pas simple. Par exemple:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
Ce n'est pas permis. Comment faire fonctionner quelque chose comme ça?
Je suis étonné que les requêtes LINQ ne soient pas autorisées sur DataTables!
Réponses:
Vous ne pouvez pas la requête contre
DataTable
l » Rows collection, carDataRowCollection
ne met pas en œuvreIEnumerable<T>
. Vous devez utiliser l'AsEnumerable()
extension pourDataTable
. Ainsi:Et comme le dit @Keith , vous devrez ajouter une référence à System.Data.DataSetExtensions
AsEnumerable()
retourneIEnumerable<DataRow>
. Si vous devez convertirIEnumerable<DataRow>
en unDataTable
, utilisez l'CopyToDataTable()
extension.Ci-dessous est une requête avec Lambda Expression,
la source
using System.Data;
myDataTable.Rows
plutôt comme l'a suggéré @JoelFan.myDataTable.Rows
est parce que lamyRow
variable est explicitement transtypée enDataRow
. Une fois compilée, cette requête est réécritemyDataTable.Rows.Cast<DataRow>().Where(myRow => (int)myRow["RowNo"] == 1)
. Personnellement, je ne trouve pas l'appel àAsEnumerable()
plus compliqué que l'appel àCast<DataRow>()
. Pour autant que je sache, les performances sont les mêmes, donc c'est juste une question de préférence.la source
(int)myRow["RowNo"]
par le formulaire génériquemyRow.Field<int>("RowNo")
pour prendre en charge plus facilement les types nullables.Ce n'est pas qu'ils n'étaient délibérément pas autorisés sur DataTables, c'est juste que DataTables est antérieur 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 sécurité de type. Les DataTables ne sont pas fortement typées. C'est la même raison pour laquelle les gens ne peuvent pas interroger une ArrayList, par exemple.
Pour que Linq fonctionne, vous devez mapper vos résultats par rapport à des objets de type sécurisé et les interroger à la place.
la source
Comme l'a dit @ ch00k:
Vous devez également ajouter une référence de projet à
System.Data.DataSetExtensions
la source
myRow
ou utilisez-Cast<DataRow>()
leRows
. Mieux à utiliserAsEnumerable()
.System.Linq
,System.Data.DataSetExtensions
puismyDataTable.Rows
retournez une collection énumérable deDataRow
toute façon. Cela a peut-être changé, cela fait une décennie que je ne l'ai pas utilisé.DataSet
extensions ne soient pas entrées dans .NET Core ou .NET Standard, elles étaient déjà obsolètes lorsque j'ai posté cette réponse. Je ne l'utiliserais vraiment pasDataSet
dans de nouveaux projets, il existe de bien meilleurs modèles d'accès aux données, à la fois pour faciliter le codage et les performances.DataRowCollection
ne sont pas implémentésIEnumerable<T>
uniquementIEnumerable
et ne fonctionnent donc pas avec LINQ fortement typé.les champs de nom et d'âge font maintenant partie de l'objet de requête et sont accessibles comme suit : Console.WriteLine (query.name);
la source
MessageBox.Show(name)
n'est pas défini.Je me rends compte que cela a été répondu plusieurs fois, mais juste pour proposer une autre approche:
J'aime utiliser la
.Cast<T>()
méthode, cela m'aide à rester sain d'esprit en voyant le type explicite défini et au fond, je pense.AsEnumerable()
qu'il l'appelle de toute façon:ou
Comme indiqué dans les commentaires, aucun autre assemblage n'est nécessaire car il fait partie de Linq ( référence )
la source
Utilisation de LINQ pour manipuler des données dans DataSet / DataTable
la source
System.Data.DataSetExtensions
.la source
Essayez cette simple ligne de requête:
la source
Vous pouvez utiliser LINQ pour des objets de la collection Rows, comme ceci:
la source
DataTable.Rows
n'implémente pasIEnumerable
, je ne vois pas comment cette requête pourrait être compilée.C'est un moyen simple qui fonctionne pour moi et utilise des expressions lambda:
Ensuite, si vous voulez une valeur particulière:
la source
Essaye ça
la source
Très probablement, les classes pour DataSet, DataTable et DataRow sont déjà définies dans la solution. Si tel est le cas, vous n'aurez pas besoin de la référence DataSetExtensions.
Ex. Nom de la classe DataSet-> CustomSet, nom de la classe DataRow-> CustomTableRow (avec les colonnes définies: RowNo, ...)
Ou (comme je préfère)
la source
la source
Dans mon application, j'ai trouvé que l'utilisation de LINQ to Datasets avec l'extension AsEnumerable () pour DataTable comme suggéré dans la réponse était extrêmement lente. Si vous souhaitez optimiser la vitesse, utilisez la bibliothèque Json.Net de James Newtonking ( http://james.newtonking.com/json/help/index.html )
la source
System.Data.DataRow
objets lourds . Le tableau de données sérialisé et analysé crée des données légères composées uniquement des noms de colonne et des valeurs de chaque ligne. Lorsque la requête s'exécute, elle charge les données en mémoire, ce qui peut impliquer un échange pour un grand ensemble de données. Parfois, la surcharge de plusieurs opérations est inférieure à celle de la copie de grandes quantités de données dans et hors de la mémoire.Pour VB.NET Le code ressemblera à ceci:
la source
la source
Exemple sur la façon d'y parvenir fourni ci-dessous:
la source
Essaye ça...
la source
Vous pouvez le faire fonctionner élégamment via linq comme ceci:
Ou comme linq dynamique ceci (AsDynamic est appelé directement sur DataSet):
Je préfère la dernière approche alors qu'elle est la plus flexible. PS: N'oubliez pas de connecter la
System.Data.DataSetExtensions.dll
référencela source
vous pouvez essayer cela, mais vous devez être sûr du type de valeurs pour chaque colonne
la source
Je propose la solution suivante:
En regardant la documentation DataView , la première chose que nous pouvons voir est la suivante:
Ce que je retiens de cela, c'est que DataTable est destiné à stocker uniquement des données et DataView est là nous permet de "requête" contre le DataTable.
Voici comment cela fonctionne dans ce cas particulier:
Vous essayez d'implémenter l'instruction SQL
dans "Langage DataTable". En C #, nous le lirions comme ceci:
qui ressemble en C # à ceci:
la source
la source