Ich versuche, eine LINQ-Abfrage für ein DataTable-Objekt durchzuführen, und stelle bizarrerweise fest, dass das Ausführen solcher Abfragen für DataTables nicht einfach ist. Zum Beispiel:
var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;
Das ist nicht erlaubt. Wie bringe ich so etwas zum Laufen?
Ich bin erstaunt, dass LINQ-Abfragen in DataTables nicht zulässig sind!
Antworten:
Sie können nicht Abfrage der
DataTable
‚s Zeilen Sammlung, daDataRowCollection
nicht implementiertIEnumerable<T>
. Sie müssen dieAsEnumerable()
Erweiterung für verwendenDataTable
. Wie so:Und wie @Keith sagt, müssen Sie einen Verweis auf System.Data.DataSetExtensions hinzufügen
AsEnumerable()
kehrt zurückIEnumerable<DataRow>
. Wenn Sie konvertieren müssen ,IEnumerable<DataRow>
um einDataTable
, verwenden Sie dieCopyToDataTable()
Erweiterung.Unten ist eine Abfrage mit Lambda-Ausdruck,
quelle
using System.Data;
myDataTable.Rows
stattdessen wie von @JoelFan vorgeschlagen.myDataTable.Rows
ist, dass diemyRow
Variable explizit in umgewandelt wirdDataRow
. Wenn es kompiliert wird, wird diese Abfrage in neu geschriebenmyDataTable.Rows.Cast<DataRow>().Where(myRow => (int)myRow["RowNo"] == 1)
. Persönlich finde ich den Anruf zuAsEnumerable()
nicht komplizierter als den Anruf zuCast<DataRow>()
. Soweit ich weiß, ist die Leistung dieselbe, es ist also nur eine Frage der Präferenz.quelle
(int)myRow["RowNo"]
das generische Formular ersetze,myRow.Field<int>("RowNo")
um nullbare Typen bequemer zu unterstützen.Es ist nicht so, dass sie absichtlich nicht in DataTables erlaubt waren, es ist nur so, dass DataTables die IQueryable- und generischen IEnumerable-Konstrukte vorab datiert, für die Linq-Abfragen ausgeführt werden können.
Beide Schnittstellen erfordern eine Sicherheitsüberprüfung des Sortiertyps. DataTables sind nicht stark typisiert. Dies ist der gleiche Grund, warum Benutzer beispielsweise keine Abfrage für eine ArrayList durchführen können.
Damit Linq funktioniert, müssen Sie Ihre Ergebnisse typsicheren Objekten zuordnen und stattdessen abfragen.
quelle
Wie @ ch00k sagte:
Sie müssen auch einen Projektverweis hinzufügen
System.Data.DataSetExtensions
quelle
myRow
oder VerwendungCast<DataRow>()
aufRows
. Besser zu benutzenAsEnumerable()
.System.Linq
undSystem.Data.DataSetExtensions
dann zurückgeben . Das könnte sich geändert haben, es ist ein Jahrzehnt her, seit ich es benutzt habe.myDataTable.Rows
DataRow
DataSet
Erweiterungen es nicht in .NET Core oder .NET Standard geschafft haben. Sie waren bereits veraltet, als ich diese Antwort veröffentlichte. Ich würde es wirklich nichtDataSet
in neuen Projekten verwenden, es gibt weitaus bessere Datenzugriffsmodelle, sowohl für die einfache Codierung als auch für die Leistung.DataRowCollection
implementieren aber nichtIEnumerable<T>
nurIEnumerable
und funktionieren daher nicht mit stark typisiertem LINQ.Die Felder Name und Alter sind jetzt Teil des Abfrageobjekts und können wie folgt aufgerufen werden: Console.WriteLine (query.name);
quelle
MessageBox.Show(name)
ist undefiniert.Mir ist klar, dass dies einige Male beantwortet wurde, aber nur um einen anderen Ansatz anzubieten:
Ich benutze die
.Cast<T>()
Methode gerne , sie hilft mir dabei, den expliziten Typ zu definieren, der tief definiert ist, und ich denke, er.AsEnumerable()
nennt ihn sowieso:oder
Wie in den Kommentaren erwähnt, werden keine weiteren Baugruppen benötigt, da diese Teil von Linq ( Referenz ) sind.
quelle
Verwenden von LINQ zum Bearbeiten von Daten in DataSet / DataTable
quelle
System.Data.DataSetExtensions
.quelle
Versuchen Sie diese einfache Abfragezeile:
quelle
Sie können LINQ für Objekte in der Rows-Auflistung verwenden, z. B.:
quelle
DataTable.Rows
nicht implementiertIEnumerable
, kann ich nicht sehen, wie diese Abfrage kompiliert werden könnte.Dies ist eine einfache Methode, die für mich funktioniert und Lambda-Ausdrücke verwendet:
Wenn Sie dann einen bestimmten Wert wünschen:
quelle
Versuche dies
quelle
Höchstwahrscheinlich sind die Klassen für DataSet, DataTable und DataRow bereits in der Lösung definiert. In diesem Fall benötigen Sie die DataSetExtensions-Referenz nicht.
Ex. DataSet-Klassenname-> CustomSet, DataRow-Klassenname-> CustomTableRow (mit definierten Spalten: RowNo, ...)
Oder (wie ich es vorziehe)
quelle
quelle
In meiner Anwendung stellte ich fest, dass die Verwendung von LINQ für Datensätze mit der Erweiterung AsEnumerable () für DataTable, wie in der Antwort vorgeschlagen, äußerst langsam war. Wenn Sie an einer Geschwindigkeitsoptimierung interessiert sind, verwenden Sie die Json.Net-Bibliothek von James Newtonking ( http://james.newtonking.com/json/help/index.html ).
quelle
System.Data.DataRow
Objekte. Die serialisierte und analysierte Datentabelle erstellt kompakte Daten, die nur aus den Spaltennamen und Werten jeder Zeile bestehen. Wenn die Abfrage ausgeführt wird, werden die Daten in den Speicher geladen, was bei einem großen Dataset möglicherweise einen Austausch erfordert. Manchmal ist der Aufwand für mehrere Vorgänge geringer als der Aufwand für das Kopieren großer Datenmengen in den und aus dem Speicher.Für VB.NET Der Code sieht folgendermaßen aus:
quelle
quelle
Ein Beispiel dafür, wie dies erreicht werden kann, finden Sie unten:
quelle
Versuche dies...
quelle
Sie können es elegant über linq wie folgt arbeiten lassen:
Oder wie bei Dynamic Linq (AsDynamic wird direkt in DataSet aufgerufen):
Ich bevorzuge den letzten Ansatz, während er am flexibelsten ist. PS: Vergessen Sie nicht, die
System.Data.DataSetExtensions.dll
Referenz anzuschließenquelle
Sie können dies versuchen, aber Sie müssen sicher sein, welche Art von Werten für jede Spalte gilt
quelle
Ich schlage folgende Lösung vor:
In der DataView-Dokumentation sehen wir zunächst Folgendes :
Daraus ergibt sich, dass DataTable nur Daten speichern soll und DataView es uns ermöglicht, die DataTable abzufragen.
So funktioniert das in diesem speziellen Fall:
Sie versuchen, die SQL-Anweisung zu implementieren
in "DataTable-Sprache". In C # würden wir es so lesen:
was in C # so aussieht:
quelle
quelle