Exemplarische Vorgehensweise: Schreiben von Abfragen in C# (LINQ)
Diese exemplarische Vorgehensweise veranschaulicht die C#-Sprachfunktionen, die zum Schreiben von LINQ-Abfrageausdrücke verwendet werden.
Erstellen eines C#-Projekts
Hinweis
Die folgenden Anweisungen gelten für Visual Studio. Wenn Sie eine andere Entwicklungsumgebung verwenden, erstellen Sie ein Konsolenprojekt mit einem Verweis auf „System.Core.dll“ und eine using
-Direktive für den Namespace System.Linq.
So erstellen Sie ein Projekt in Visual Studio
Starten Sie Visual Studio.
Wählen Sie in der Menüleiste Datei, Neu, Projektaus.
Das Dialogfeld Neues Projekt wird angezeigt.
Erweitern Sie nacheinander Installiert, Vorlagen, Visual C# , und wählen Sie dann Konsolenanwendung aus.
Geben Sie im Textfeld Name einen anderen Namen ein, oder übernehmen Sie den Standardnamen, und wählen Sie dann die Schaltfläche OK aus.
Das neue Projekt wird im Projektmappen-Explorer angezeigt.
Beachten Sie, dass Ihr Projekt einen Verweis auf „System.Core.dll“ und eine
using
-Direktive für den Namespace System.Linq enthält.
Erstellen einer In-Memory-Datenquelle
Die Datenquelle für die Abfragen ist eine einfache Liste mit Student
-Objekten. Jeder Student
-Datensatz umfasst einen Vornamen, einen Nachnamen und ein Array von Ganzzahlen, das die Testergebnisse der einzelnen Studenten in der Klasse darstellt. Kopieren Sie diesen Code in Ihr Projekt. Beachten Sie die folgenden Eigenschaften:
Die
Student
-Klasse besteht aus automatisch implementierten Eigenschaften.Jeder Student in der Liste wird mit einem Objektinitialisierer initialisiert.
Die Liste selbst wird mit einem Auflistungsinitialisierer initialisiert.
Die gesamte Datenstruktur wird ohne explizite Aufrufe eines beliebigen Konstruktors oder expliziten Memberzugriff initialisiert und instanziiert. Weitere Informationen zu diesen neuen Funktionen finden Sie unter Automatisch implementierte Eigenschaften und Objekt- und Auflistungsinitialisierer.
So fügen Sie die Datenquelle hinzu
Fügen Sie die
Student
-Klasse und die initialisierte Liste der Studenten zurProgram
-Klasse in Ihrem Projekt hinzu.public class Student { public string First { get; set; } public string Last { get; set; } public int ID { get; set; } public List<int> Scores; } // Create a data source by using a collection initializer. static List<Student> students = [ new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 92, 81, 60}}, new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}}, new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int> {88, 94, 65, 91}}, new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int> {97, 89, 85, 82}}, new Student {First="Debra", Last="Garcia", ID=115, Scores= new List<int> {35, 72, 91, 70}}, new Student {First="Fadi", Last="Fakhouri", ID=116, Scores= new List<int> {99, 86, 90, 94}}, new Student {First="Hanying", Last="Feng", ID=117, Scores= new List<int> {93, 92, 80, 87}}, new Student {First="Hugo", Last="Garcia", ID=118, Scores= new List<int> {92, 90, 83, 78}}, new Student {First="Lance", Last="Tucker", ID=119, Scores= new List<int> {68, 79, 88, 92}}, new Student {First="Terry", Last="Adams", ID=120, Scores= new List<int> {99, 82, 81, 79}}, new Student {First="Eugene", Last="Zabokritski", ID=121, Scores= new List<int> {96, 85, 91, 60}}, new Student {First="Michael", Last="Tucker", ID=122, Scores= new List<int> {94, 92, 91, 91}} ];
So fügen Sie einen neuen Studenten zur Liste der Studenten hinzu
- Fügen Sie einen neuen
Student
zurStudents
-Liste hinzu, und verwenden Sie einen Namen und ein Testergebnis Ihrer Wahl. Geben Sie alle Informationen für den neuen Studenten ein, um sich mit der Syntax für den Objektinitialisierer vertraut zu machen.
Erstellen der Abfrage
So erstellen Sie eine einfache Abfrage
Erstellen Sie in der
Main
-Methode der Anwendung eine einfache Abfrage, die bei Ausführung eine Liste aller Studenten erzeugt, deren Ergebnis im ersten Test höher als 90 war. Beachten Sie, dass der Typ der AbfrageStudent
ist, da das gesamteIEnumerable<Student>
-Objekt ausgewählt wird. Obwohl der Code auch die implizite Typisierung mithilfe des Schlüsselworts var verwenden könnte, wird die explizite Typisierung verwendet, um die Ergebnisse deutlich darzustellen. (Weitere Informationen zuvar
finden Sie unter Implizit typisierte lokale Variablen.)Beachten Sie auch, dass
student
, die Bereichsvariable der Abfrage, als Verweis auf jedenStudent
in der Quelle dient und Memberzugriff auf jedes Objekt bietet.
// Create the query.
// The first line could also be written as "var studentQuery ="
IEnumerable<Student> studentQuery =
from student in students
where student.Scores[0] > 90
select student;
Ausführen der Abfrage
So führen Sie die Abfrage aus
Schreiben Sie jetzt die
foreach
-Schleife, die das Ausführen der Abfrage auslöst. Beachten Sie Folgendes beim Code:Auf jedes Element in der zurückgegebenen Sequenz wird über die Iterationsvariable in der
foreach
-Schleife zugegriffen.Der Typ dieser Variable ist
Student
, und der Typ der Abfragevariable,IEnumerable<Student>
, ist kompatibel.
Erstellen Sie die Anwendung, und führen Sie sie aus, nachdem Sie diesen Code hinzugefügt haben, um die Ergebnisse im Fenster Konsole anzeigen zu lassen.
// Execute the query.
// var could be used here also.
foreach (Student student in studentQuery)
{
Console.WriteLine("{0}, {1}", student.Last, student.First);
}
// Output:
// Omelchenko, Svetlana
// Garcia, Cesar
// Fakhouri, Fadi
// Feng, Hanying
// Garcia, Hugo
// Adams, Terry
// Zabokritski, Eugene
// Tucker, Michael
So fügen Sie eine weitere Filterbedingung hinzu
Sie können mehrere boolesche Bedingungen in der
where
-Klausel kombinieren, um eine Abfrage weiter zu optimieren. Der folgende Code fügt eine Bedingung hinzu, sodass die Abfrage die Studenten zurückgibt, deren erstes Ergebnis höher als 90 und das letzte Ergebnis niedriger als 80 war. Diewhere
-Klausel sollte in etwa dem folgenden Code entsprechen.where student.Scores[0] > 90 && student.Scores[3] < 80
Weitere Informationen finden Sie unter where-Klausel.
Ändern der Abfrage
So sortieren Sie die Ergebnisse
Es ist einfacher, die Ergebnisse zu überprüfen, wenn sie geordnet dargestellt werden. Sie können die zurückgegebene Sequenz nach einem beliebigen zugänglichen Feld in den Quellelementen sortieren. Die folgende
orderby
-Klausel ordnet die Ergebnisse z.B. in alphabetischer Reihenfolge (A bis Z) nach dem Nachnamen jedes Studenten. Fügen Sie die folgendeorderby
-Klausel direkt nach derwhere
-Anweisung und vor derselect
-Anweisung zu Ihrer Abfrage hinzu:orderby student.Last ascending
Ändern Sie nun die
orderby
-Klausel so, dass sie die Ergebnisse in umgekehrter Reihenfolge gemäß dem Ergebnis im ersten Test sortiert, vom höchsten zum niedrigsten Ergebnis.orderby student.Scores[0] descending
Ändern Sie die
WriteLine
-Formatzeichenfolge so, dass die Ergebnisse angezeigt werden:Console.WriteLine("{0}, {1} {2}", student.Last, student.First, student.Scores[0]);
Weitere Informationen finden Sie unter orderby-Klausel.
So gruppieren Sie die Ergebnisse
Die Gruppierung ist eine leistungsstarke Funktion in Abfrageausdrücken. Eine Abfrage mit einer group-Klausel erzeugt eine Sequenz von Gruppen, in der jede Gruppe einen
Key
und eine Sequenz enthält, die aus allen Mitgliedern dieser Gruppe besteht. Die folgende neue Abfrage gruppiert die Studenten mit dem ersten Buchstaben ihres Nachnamens als Schlüssel.IEnumerable<IGrouping<char, Student>> studentQuery2 = from student in students group student by student.Last[0];
Beachten Sie, dass sich der Typ der Abfrage jetzt geändert ist. Sie erzeugt nun eine Sequenz von Gruppen mit einem
char
-Typ als Schlüssel und eine Sequenz vonStudent
-Objekten. Da der Typ der Abfrage geändert wurde, ändert folgender Code ebenfalls dieforeach
-Ausführungsschleife:foreach (IGrouping<char, Student> studentGroup in studentQuery2) { Console.WriteLine(studentGroup.Key); foreach (Student student in studentGroup) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } } // Output: // O // Omelchenko, Svetlana // O'Donnell, Claire // M // Mortensen, Sven // G // Garcia, Cesar // Garcia, Debra // Garcia, Hugo // F // Fakhouri, Fadi // Feng, Hanying // T // Tucker, Lance // Tucker, Michael // A // Adams, Terry // Z // Zabokritski, Eugene
Führen Sie die Anwendung aus, und zeigen Sie die Ergebnisse im Fenster Konsole an.
Weitere Informationen finden Sie unter group-Klausel.
So legen Sie Variablen als implizit typisiert fest
Das explizite Codieren von
IEnumerables
vonIGroupings
kann schnell mühsam werden. Sie können dieselbe Abfrage undforeach
-Schleife viel einfacher mithilfe vonvar
schreiben. Das Schlüsselwortvar
ändert die Typen Ihres Objekts nicht; es weist nur den Compiler an, die Typen abzuleiten. Ändern Sie den Typ vonstudentQuery
und der Iterationsvariablegroup
zuvar
, und führen Sie die Abfrage erneut aus. Beachten Sie, dass die Iterationsvariable in der innerenforeach
-Schleife immer noch alsStudent
typisiert ist und die Abfrage so ausgeführt wird wie zuvor. Ändern Sie die Iterationsvariablestudent
zuvar
, und führen Sie die Abfrage erneut aus. Sie sehen, dass Sie genau die gleichen Ergebnisse erhalten.var studentQuery3 = from student in students group student by student.Last[0]; foreach (var groupOfStudents in studentQuery3) { Console.WriteLine(groupOfStudents.Key); foreach (var student in groupOfStudents) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } } // Output: // O // Omelchenko, Svetlana // O'Donnell, Claire // M // Mortensen, Sven // G // Garcia, Cesar // Garcia, Debra // Garcia, Hugo // F // Fakhouri, Fadi // Feng, Hanying // T // Tucker, Lance // Tucker, Michael // A // Adams, Terry // Z // Zabokritski, Eugene
Weitere Informationen zu var finden Sie unter Implizit typisierte lokale Variablen.
So sortieren Sie die Gruppen nach ihren Schlüsselwerten
Wenn Sie die vorherige Abfrage ausführen, werden Sie feststellen, dass die Gruppen nicht alphabetischer angeordnet sind. Um dies zu ändern, müssen Sie eine
orderby
-Klausel nach dergroup
-Klausel angeben. Sie benötigen aber zuerst einen Bezeichner, der als Verweis auf die durch diegroup
-Klausel erstellte Gruppe dient, bevor Sie eineorderby
-Klausel verwenden können. Geben Sie den Bezeichner mithilfe des Schlüsselwortsinto
wie folgt an:var studentQuery4 = from student in students group student by student.Last[0] into studentGroup orderby studentGroup.Key select studentGroup; foreach (var groupOfStudents in studentQuery4) { Console.WriteLine(groupOfStudents.Key); foreach (var student in groupOfStudents) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } } // Output: //A // Adams, Terry //F // Fakhouri, Fadi // Feng, Hanying //G // Garcia, Cesar // Garcia, Debra // Garcia, Hugo //M // Mortensen, Sven //O // Omelchenko, Svetlana // O'Donnell, Claire //T // Tucker, Lance // Tucker, Michael //Z // Zabokritski, Eugene
Wenn Sie diese Abfrage ausführen, werden Sie feststellen, dass die Gruppen nun in alphabetischer Reihenfolge sortiert sind.
So führen Sie einen Bezeichner mit „let“ ein
Sie können das Schlüsselwort
let
verwenden, um einen Bezeichner für ein beliebiges Ausdrucksergebnis in den Abfrageausdruck einzuführen. Dieser Bezeichner ist sehr praktisch, wie im folgenden Beispiel zu sehen ist; er kann auch die Leistung verbessern, da die Ergebnisse eines Ausdrucks gespeichert werden und nicht mehrfach berechnet werden müssen.// studentQuery5 is an IEnumerable<string> // This query returns those students whose // first test score was higher than their // average score. var studentQuery5 = from student in students let totalScore = student.Scores[0] + student.Scores[1] + student.Scores[2] + student.Scores[3] where totalScore / 4 < student.Scores[0] select student.Last + " " + student.First; foreach (string s in studentQuery5) { Console.WriteLine(s); } // Output: // Omelchenko Svetlana // O'Donnell Claire // Mortensen Sven // Garcia Cesar // Fakhouri Fadi // Feng Hanying // Garcia Hugo // Adams Terry // Zabokritski Eugene // Tucker Michael
Weitere Informationen finden Sie unter let-Klausel.
So verwenden Sie die Methodensyntax in einem Abfrageausdruck
Wie unter Abfragesyntax und Methodensyntax in LINQ beschrieben, können einige Abfrageoperationen nur durch Verwendung der Methodensyntax ausgedrückt werden. Der folgende Code berechnet das Gesamtergebnis für jeden
Student
in der Quellsequenz und ruft dann dieAverage()
-Methode für die Ergebnisse der Abfrage auf, um die durchschnittliche Punktzahl der Klasse zu berechnen.var studentQuery6 = from student in students let totalScore = student.Scores[0] + student.Scores[1] + student.Scores[2] + student.Scores[3] select totalScore; double averageScore = studentQuery6.Average(); Console.WriteLine("Class average score = {0}", averageScore); // Output: // Class average score = 334.166666666667
So transformieren oder projizieren Sie in die select-Klausel
Es kommt sehr häufig vor, dass eine Abfrage eine Sequenz erzeugt, deren Elemente sich von den Elementen in den Quellsequenzen unterscheiden. Löschen Sie oder kommentieren Sie die vorherige Abfrage und Ausführungsschleife aus, und ersetzen Sie sie durch den folgenden Code. Beachten Sie, dass die Abfrage eine Sequenz von Zeichenfolgen zurückgibt (nicht
Students
). Dies spiegelt sich in derforeach
-Schleife wider.IEnumerable<string> studentQuery7 = from student in students where student.Last == "Garcia" select student.First; Console.WriteLine("The Garcias in the class are:"); foreach (string s in studentQuery7) { Console.WriteLine(s); } // Output: // The Garcias in the class are: // Cesar // Debra // Hugo
Der vorherige Code in dieser exemplarischen Vorgehensweise hat gezeigt, dass das durchschnittliche Ergebnis der Klasse ungefähr 334 beträgt. Zum Erstellen einer Sequenz von
Students
mit ihrerStudent ID
, deren Ergebnis höher ist als der Klassendurchschnitt, können Sie einen anonymen Typ in derselect
-Anweisung verwenden:
Nächste Schritte
Nachdem Sie nun mit den grundlegenden Aspekten der Arbeit mit Abfragen in C# vertraut sind, sind Sie nun bereit, die Dokumentation und Beispiele für bestimmte LINQ-Anbieter zu lesen, an denen Sie interessiert sind:
Siehe auch
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für