Exemplarische Vorgehensweise: Schreiben von Abfragen in C# (LINQ)Walkthrough: Writing Queries in C# (LINQ)

Diese exemplarische Vorgehensweise veranschaulicht die C#-Sprachfunktionen, die zum Schreiben von LINQ-Abfrageausdrücke verwendet werden.This walkthrough demonstrates the C# language features that are used to write LINQ query expressions.

Erstellen eines C#-ProjektsCreate a C# Project

Hinweis

Die folgenden Anweisungen gelten für Visual Studio.The following instructions are for 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.If you are using a different development environment, create a console project with a reference to System.Core.dll and a using directive for the System.Linq namespace.

So erstellen Sie ein Projekt in Visual StudioTo create a project in Visual Studio

  1. Starten Sie Visual Studio.Start Visual Studio.

  2. Wählen Sie in der Menüleiste Datei, Neu, Projektaus.On the menu bar, choose File, New, Project.

    Das Dialogfeld Neues Projekt wird angezeigt.The New Project dialog box opens.

  3. Erweitern Sie nacheinander Installiert, Vorlagen, Visual C#, und wählen Sie dann Konsolenanwendung aus.Expand Installed, expand Templates, expand Visual C#, and then choose Console Application.

  4. Geben Sie im Textfeld Name einen anderen Namen ein, oder übernehmen Sie den Standardnamen, und wählen Sie dann die Schaltfläche OK aus.In the Name text box, enter a different name or accept the default name, and then choose the OK button.

    Das neue Projekt wird im Projektmappen-Explorer angezeigt.The new project appears in Solution Explorer.

  5. Beachten Sie, dass Ihr Projekt einen Verweis auf „System.Core.dll“ und eine using-Direktive für den Namespace System.Linq enthält.Notice that your project has a reference to System.Core.dll and a using directive for the System.Linq namespace.

Erstellen einer In-Memory-DatenquelleCreate an in-Memory Data Source

Die Datenquelle für die Abfragen ist eine einfache Liste mit Student-Objekten.The data source for the queries is a simple list of Student objects. Jeder Student-Datensatz umfasst einen Vornamen, einen Nachnamen und ein Array von Ganzzahlen, das die Testergebnisse der einzelnen Studenten in der Klasse darstellt.Each Student record has a first name, last name, and an array of integers that represents their test scores in the class. Kopieren Sie diesen Code in Ihr Projekt.Copy this code into your project. Beachten Sie die folgenden Eigenschaften:Note the following characteristics:

  • Die Student-Klasse besteht aus automatisch implementierten Eigenschaften.The Student class consists of auto-implemented properties.

  • Jeder Student in der Liste wird mit einem Objektinitialisierer initialisiert.Each student in the list is initialized with an object initializer.

  • Die Liste selbst wird mit einem Auflistungsinitialisierer initialisiert.The list itself is initialized with a collection initializer.

Die gesamte Datenstruktur wird ohne explizite Aufrufe eines beliebigen Konstruktors oder expliziten Memberzugriff initialisiert und instanziiert.This whole data structure will be initialized and instantiated without explicit calls to any constructor or explicit member access. Weitere Informationen zu diesen neuen Funktionen finden Sie unter Automatisch implementierte Eigenschaften und Objekt- und Auflistungsinitialisierer.For more information about these new features, see Auto-Implemented Properties and Object and Collection Initializers.

So fügen Sie die Datenquelle hinzuTo add the data source

  • Fügen Sie die Student-Klasse und die initialisierte Liste der Studenten zur Program-Klasse in Ihrem Projekt hinzu.Add the Student class and the initialized list of students to the Program class in your project.

    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 List<Student>
    {
       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 hinzuTo add a new Student to the Students list

  1. Fügen Sie einen neuen Student zur Students-Liste hinzu, und verwenden Sie einen Namen und ein Testergebnis Ihrer Wahl.Add a new Student to the Students list and use a name and test scores of your choice. Geben Sie alle Informationen für den neuen Studenten ein, um sich mit der Syntax für den Objektinitialisierer vertraut zu machen.Try typing all the new student information in order to better learn the syntax for the object initializer.

Erstellen der AbfrageCreate the Query

So erstellen Sie eine einfache AbfrageTo create a simple query

  • 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.In the application's Main method, create a simple query that, when it is executed, will produce a list of all students whose score on the first test was greater than 90. Beachten Sie, dass der Typ der Abfrage Student ist, da das gesamte IEnumerable<Student>-Objekt ausgewählt wird.Note that because the whole Student object is selected, the type of the query is IEnumerable<Student>. 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.Although the code could also use implicit typing by using the var keyword, explicit typing is used to clearly illustrate results. (Weitere Informationen zu var finden Sie unter Implizit typisierte lokale Variablen.)(For more information about var, see Implicitly Typed Local Variables.)

    Beachten Sie auch, dass student, die Bereichsvariable der Abfrage, als Verweis auf jeden Student in der Quelle dient und Memberzugriff auf jedes Objekt bietet.Note also that the query's range variable, student, serves as a reference to each Student in the source, providing member access for each object.

// 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 AbfrageExecute the Query

So führen Sie die Abfrage ausTo execute the query

  1. Schreiben Sie jetzt die foreach-Schleife, die das Ausführen der Abfrage auslöst.Now write the foreach loop that will cause the query to execute. Beachten Sie Folgendes beim Code:Note the following about the code:

    • Auf jedes Element in der zurückgegebenen Sequenz wird über die Iterationsvariable in der foreach-Schleife zugegriffen.Each element in the returned sequence is accessed through the iteration variable in the foreach loop.

    • Der Typ dieser Variable ist Student, und der Typ der Abfragevariable, IEnumerable<Student>, ist kompatibel.The type of this variable is Student, and the type of the query variable is compatible, IEnumerable<Student>.

  2. 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.After you have added this code, build and run the application to see the results in the Console window.

// 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 hinzuTo add another filter condition

  1. Sie können mehrere boolesche Bedingungen in der where-Klausel kombinieren, um eine Abfrage weiter zu optimieren.You can combine multiple Boolean conditions in the where clause in order to further refine a query. 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.The following code adds a condition so that the query returns those students whose first score was over 90 and whose last score was less than 80. Die where-Klausel sollte in etwa dem folgenden Code entsprechen.The where clause should resemble the following code.

    where student.Scores[0] > 90 && student.Scores[3] < 80  
    

    Weitere Informationen finden Sie unter where-Klausel.For more information, see where clause.

Ändern der AbfrageModify the Query

So sortieren Sie die ErgebnisseTo order the results

  1. Es ist einfacher, die Ergebnisse zu überprüfen, wenn sie geordnet dargestellt werden.It will be easier to scan the results if they are in some kind of order. Sie können die zurückgegebene Sequenz nach einem beliebigen zugänglichen Feld in den Quellelementen sortieren.You can order the returned sequence by any accessible field in the source elements. Die folgende orderby-Klausel ordnet die Ergebnisse z.B. in alphabetischer Reihenfolge (A bis Z) nach dem Nachnamen jedes Studenten.For example, the following orderby clause orders the results in alphabetical order from A to Z according to the last name of each student. Fügen Sie die folgende orderby-Klausel direkt nach der where-Anweisung und vor der select-Anweisung zu Ihrer Abfrage hinzu:Add the following orderby clause to your query, right after the where statement and before the select statement:

    orderby student.Last ascending  
    
  2. Ä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.Now change the orderby clause so that it orders the results in reverse order according to the score on the first test, from the highest score to the lowest score.

    orderby student.Scores[0] descending  
    
  3. Ändern Sie die WriteLine-Formatzeichenfolge so, dass die Ergebnisse angezeigt werden:Change the WriteLine format string so that you can see the scores:

    Console.WriteLine("{0}, {1} {2}", student.Last, student.First, student.Scores[0]);  
    

    Weitere Informationen finden Sie unter orderby-Klausel.For more information, see orderby clause.

So gruppieren Sie die ErgebnisseTo group the results

  1. Die Gruppierung ist eine leistungsstarke Funktion in Abfrageausdrücken.Grouping is a powerful capability in query expressions. 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.A query with a group clause produces a sequence of groups, and each group itself contains a Key and a sequence that consists of all the members of that group. Die folgende neue Abfrage gruppiert die Studenten mit dem ersten Buchstaben ihres Nachnamens als Schlüssel.The following new query groups the students by using the first letter of their last name as the key.

    // studentQuery2 is an IEnumerable<IGrouping<char, Student>>
    var studentQuery2 =
        from student in students
        group student by student.Last[0];
    
  2. Beachten Sie, dass sich der Typ der Abfrage jetzt geändert ist.Note that the type of the query has now changed. Sie erzeugt nun eine Sequenz von Gruppen mit einem char-Typ als Schlüssel und eine Sequenz von Student-Objekten.It now produces a sequence of groups that have a char type as a key, and a sequence of Student objects. Da der Typ der Abfrage geändert wurde, ändert folgender Code ebenfalls die foreach-Ausführungsschleife:Because the type of the query has changed, the following code changes the foreach execution loop also:

    // studentGroup is a IGrouping<char, Student>
    foreach (var 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
    
  3. Führen Sie die Anwendung aus, und zeigen Sie die Ergebnisse im Fenster Konsole an.Run the application and view the results in the Console window.

    Weitere Informationen finden Sie unter group-Klausel.For more information, see group clause.

So legen Sie Variablen als implizit typisiert festTo make the variables implicitly typed

  1. Das explizite Codieren von IEnumerables von IGroupings kann schnell mühsam werden.Explicitly coding IEnumerables of IGroupings can quickly become tedious. Sie können dieselbe Abfrage und foreach-Schleife viel einfacher mithilfe von var schreiben.You can write the same query and foreach loop much more conveniently by using var. Das Schlüsselwort var ändert die Typen Ihres Objekts nicht; es weist nur den Compiler an, die Typen abzuleiten.The var keyword does not change the types of your objects; it just instructs the compiler to infer the types. Ändern Sie den Typ von studentQuery und der Iterationsvariable group zu var, und führen Sie die Abfrage erneut aus.Change the type of studentQuery and the iteration variable group to var and rerun the query. Beachten Sie, dass die Iterationsvariable in der inneren foreach-Schleife immer noch als Student typisiert ist und die Abfrage so ausgeführt wird wie zuvor.Note that in the inner foreach loop, the iteration variable is still typed as Student, and the query works just as before. Ändern Sie die Iterationsvariable s zu var, und führen Sie die Abfrage erneut aus.Change the s iteration variable to var and run the query again. Sie sehen, dass Sie genau die gleichen Ergebnisse erhalten.You see that you get exactly the same results.

    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.For more information about var, see Implicitly Typed Local Variables.

So sortieren Sie die Gruppen nach ihren SchlüsselwertenTo order the groups by their key value

  1. Wenn Sie die vorherige Abfrage ausführen, werden Sie feststellen, dass die Gruppen nicht alphabetischer angeordnet sind.When you run the previous query, you notice that the groups are not in alphabetical order. Um dies zu ändern, müssen Sie eine orderby-Klausel nach der group-Klausel angeben.To change this, you must provide an orderby clause after the group clause. Sie benötigen aber zuerst einen Bezeichner, der als Verweis auf die durch die group-Klausel erstellte Gruppe dient, bevor Sie eine orderby-Klausel verwenden können.But to use an orderby clause, you first need an identifier that serves as a reference to the groups created by the group clause. Geben Sie den Bezeichner mithilfe des Schlüsselworts into wie folgt an:You provide the identifier by using the into keyword, as follows:

    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.When you run this query, you will see the groups are now sorted in alphabetical order.

So führen Sie einen Bezeichner mit „let“ einTo introduce an identifier by using let

  1. Sie können das Schlüsselwort let verwenden, um einen Bezeichner für ein beliebiges Ausdrucksergebnis in den Abfrageausdruck einzuführen.You can use the let keyword to introduce an identifier for any expression result in the query expression. 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.This identifier can be a convenience, as in the following example, or it can enhance performance by storing the results of an expression so that it does not have to be calculated multiple times.

    // 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.For more information, see let clause.

So verwenden Sie die Methodensyntax in einem AbfrageausdruckTo use method syntax in a query expression

  1. Wie unter Abfragesyntax und Methodensyntax in LINQ beschrieben, können einige Abfrageoperationen nur durch Verwendung der Methodensyntax ausgedrückt werden.As described in Query Syntax and Method Syntax in LINQ, some query operations can only be expressed by using method syntax. Der folgende Code berechnet das Gesamtergebnis für jeden Student in der Quellsequenz und ruft dann die Average()-Methode für die Ergebnisse der Abfrage auf, um die durchschnittliche Punktzahl der Klasse zu berechnen.The following code calculates the total score for each Student in the source sequence, and then calls the Average() method on the results of that query to calculate the average score of the class. Beachten Sie die Platzierung von Klammern um den Abfrageausdruck.Note the placement of parentheses around the query expression.

    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-KlauselTo transform or project in the select clause

  1. Es kommt sehr häufig vor, dass eine Abfrage eine Sequenz erzeugt, deren Elemente sich von den Elementen in den Quellsequenzen unterscheiden.It is very common for a query to produce a sequence whose elements differ from the elements in the source sequences. Löschen Sie oder kommentieren Sie die vorherige Abfrage und Ausführungsschleife aus, und ersetzen Sie sie durch den folgenden Code.Delete or comment out your previous query and execution loop, and replace it with the following code. Beachten Sie, dass die Abfrage eine Sequenz von Zeichenfolgen zurückgibt (nicht Students). Dies spiegelt sich in der foreach-Schleife wider.Note that the query returns a sequence of strings (not Students), and this fact is reflected in the foreach loop.

    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
    
  2. Der vorherige Code in dieser exemplarischen Vorgehensweise hat gezeigt, dass das durchschnittliche Ergebnis der Klasse ungefähr 334 beträgt.Code earlier in this walkthrough indicated that the average class score is approximately 334. Zum Erstellen einer Sequenz von Students mit ihrer Student ID, deren Ergebnis höher ist als der Klassendurchschnitt, können Sie einen anonymen Typ in der select-Anweisung verwenden:To produce a sequence of Students whose total score is greater than the class average, together with their Student ID, you can use an anonymous type in the select statement:

    var studentQuery8 =
        from student in students
        let x = student.Scores[0] + student.Scores[1] +
            student.Scores[2] + student.Scores[3]
        where x > averageScore
        select new { id = student.ID, score = x };
    
    foreach (var item in studentQuery8)
    {
        Console.WriteLine("Student ID: {0}, Score: {1}", item.id, item.score);
    }
    
    // Output:
    // Student ID: 113, Score: 338
    // Student ID: 114, Score: 353
    // Student ID: 116, Score: 369
    // Student ID: 117, Score: 352
    // Student ID: 118, Score: 343
    // Student ID: 120, Score: 341
    // Student ID: 122, Score: 368
    

Nächste SchritteNext Steps

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:After you are familiar with the basic aspects of working with queries in C#, you are ready to read the documentation and samples for the specific type of LINQ provider you are interested in:

LINQ to SQLLINQ to SQL

LINQ to DataSetLINQ to DataSet

LINQ to XML (C#)LINQ to XML (C#)

LINQ to Objects (C#)LINQ to Objects (C#)

Siehe auchSee Also

Language-Integrated Query (LINQ) (C#) (Language-Integrated Query (LINQ) (C#))Language-Integrated Query (LINQ) (C#)
Erste Schritte mit LINQ in C#Getting Started with LINQ in C#
LINQ-AbfrageausdrückeLINQ Query Expressions