Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze zelfstudie maakt u een gegevensbron en schrijft u verschillende LINQ-query's. U kunt experimenteren met de query-expressies en de verschillen in de resultaten bekijken. In dit scenario ziet u de C#-taalfuncties die worden gebruikt voor het schrijven van LINQ-query-expressies. U kunt de stappen volgen om de app te bouwen en zelf experimenteren met de queries. In dit artikel wordt ervan uitgegaan dat u de nieuwste .NET SDK hebt geïnstalleerd. Als dat niet zo is, gaat u naar de pagina .NET Downloads en installeert u de nieuwste versie op uw computer.
Maak eerst de toepassing. Typ in de console de volgende opdracht:
dotnet new console -o WalkthroughWritingLinqQueries
Als u liever Visual Studio gebruikt, maakt u een nieuwe consoletoepassing met de naam WalkthroughWritingLinqQueries.
Een in-memory gegevensbron maken
De eerste stap is het maken van een gegevensbron voor uw query's. De gegevensbron voor de query's is een eenvoudige lijst met Student records. Elke Student record heeft een voornaam, familienaam en een matrix met gehele getallen die hun testscores in de klasse vertegenwoordigen. Voeg een nieuw bestand toe met de naam students.cs en kopieer de volgende code naar dat bestand:
namespace WalkthroughWritingLinqQueries;
public record Student(string First, string Last, int ID, int[] Scores);
Let op de volgende kenmerken:
- De
Studentrecord bestaat uit automatisch geïmplementeerde eigenschappen. - Elke student in de lijst wordt geïnitialiseerd met de primaire constructor.
- De reeks scores voor elke student wordt geïnitialiseerd met een primaire constructor.
Maak vervolgens een reeks Student records die fungeert als de bron van deze query. Open Program.cs en verwijder de volgende standaardcode:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Vervang deze door de volgende code waarmee een reeks Student records wordt gemaakt:
using WalkthroughWritingLinqQueries;
// Create a data source by using a collection initializer.
IEnumerable<Student> students =
[
new Student(First: "Svetlana", Last: "Omelchenko", ID: 111, Scores: [97, 92, 81, 60]),
new Student(First: "Claire", Last: "O'Donnell", ID: 112, Scores: [75, 84, 91, 39]),
new Student(First: "Sven", Last: "Mortensen", ID: 113, Scores: [88, 94, 65, 91]),
new Student(First: "Cesar", Last: "Garcia", ID: 114, Scores: [97, 89, 85, 82]),
new Student(First: "Debra", Last: "Garcia", ID: 115, Scores: [35, 72, 91, 70]),
new Student(First: "Fadi", Last: "Fakhouri", ID: 116, Scores: [99, 86, 90, 94]),
new Student(First: "Hanying", Last: "Feng", ID: 117, Scores: [93, 92, 80, 87]),
new Student(First: "Hugo", Last: "Garcia", ID: 118, Scores: [92, 90, 83, 78]),
new Student("Lance", "Tucker", 119, [68, 79, 88, 92]),
new Student("Terry", "Adams", 120, [99, 82, 81, 79]),
new Student("Eugene", "Zabokritski", 121, [96, 85, 91, 60]),
new Student("Michael", "Tucker", 122, [94, 92, 91, 91])
];
- De reeks studenten wordt geïnitialiseerd met een verzamelingsexpressie.
- Het
Studentrecordtype bevat de statische lijst van alle leerlingen/studenten. - Sommige constructor-aanroepen gebruiken benoemde argumenten om te verduidelijken welk argument overeenkomt met welke constructorparameter.
Probeer nog een paar studenten met verschillende testscores toe te voegen aan de lijst met leerlingen/studenten om meer vertrouwd te raken met de code tot nu toe.
De query maken
Vervolgens maakt u uw eerste query. Tijdens het uitvoeren van uw query wordt een lijst gegenereerd met alle leerlingen/studenten waarvan de score voor de eerste test groter is dan 90. Omdat het hele Student object is geselecteerd, is IEnumerable<Student>het type van de query. Hoewel de code ook impliciete typen kan gebruiken met behulp van het trefwoord var , wordt expliciet typen gebruikt om de resultaten duidelijk te illustreren. (Zie Impliciet getypte lokale variabelen voor meer informatie overvar.) Voeg de volgende code toe aan Program.cs, na de code waarmee de reeks leerlingen/studenten wordt gemaakt:
// 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;
De bereikvariabele van de query, student fungeert als een verwijzing naar elk Student in de bron en biedt toegang tot leden voor elk object.
De query uitvoeren
Schrijf nu de foreach lus die ervoor zorgt dat de query wordt uitgevoerd. Elk element in de geretourneerde reeks wordt geopend via de iteratievariabele in de lus foreach . Het type van deze variabele is Studenten het type van de queryvariabele is compatibel. IEnumerable<Student> Nadat u de volgende code hebt toegevoegd, bouwt en voert u de toepassing uit om de resultaten in het consolevenster weer te geven.
// Execute the query.
// var could be used here also.
foreach (Student student in studentQuery)
{
Console.WriteLine($"{student.Last}, {student.First}");
}
// Output:
// Omelchenko, Svetlana
// Garcia, Cesar
// Fakhouri, Fadi
// Feng, Hanying
// Garcia, Hugo
// Adams, Terry
// Zabokritski, Eugene
// Tucker, Michael
Als u de query verder wilt verfijnen, kunt u meerdere Booleaanse voorwaarden in de where component combineren. Met de volgende code wordt een voorwaarde toegevoegd, zodat de query die studenten retourneert waarvan de eerste score meer dan 90 is en waarvan de laatste score kleiner is dan 80. De where component moet lijken op de volgende code.
where student.Scores[0] > 90 && student.Scores[3] < 80
Probeer de voorgaande where component of experimenteer uzelf met andere filtervoorwaarden. Voor meer informatie, zie where-clausule.
De queryresultaten ordenen
Het is eenvoudiger om de resultaten te scannen als ze zich in een bepaalde volgorde bevinden. U kunt de geretourneerde volgorde rangschikken op elk toegankelijk veld in de bronelementen. Met de volgende orderby component worden de resultaten bijvoorbeeld in alfabetische volgorde van A tot Z gesorteerd op basis van de familienaam van elke student. Voeg de volgende orderby component toe aan uw query, direct na de where instructie en vóór de select instructie:
orderby student.Last ascending
Wijzig nu de orderby component zodat de resultaten in omgekeerde volgorde worden gerangschikt op basis van de score op de eerste test, van de hoogste score tot de laagste score.
orderby student.Scores[0] descending
Wijzig de WriteLine notatietekenreeks zodat u de scores kunt zien:
Console.WriteLine($"{student.Last}, {student.First} {student.Scores[0]}");
Voor meer informatie, zie orderby-clausule.
De resultaten groeperen
Groeperen is een krachtige mogelijkheid in query-expressies. Een query met een groepscomponent produceert een reeks groepen en elke groep zelf bevat een Key en een reeks die bestaat uit alle leden van die groep. Met de volgende nieuwe query worden de leerlingen/studenten gegroepeerd met behulp van de eerste letter van hun familienaam als sleutel.
IEnumerable<IGrouping<char, Student>> studentQuery =
from student in students
group student by student.Last[0];
Het type query is gewijzigd. Het produceert nu een reeks groepen met een char type als sleutel en een reeks Student objecten. De code in de foreach uitvoeringslus moet ook worden gewijzigd:
foreach (IGrouping<char, Student> studentGroup in studentQuery)
{
Console.WriteLine(studentGroup.Key);
foreach (Student student in studentGroup)
{
Console.WriteLine($" {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
Voer de toepassing uit en bekijk de resultaten in het consolevenster . Zie groepsclausule voor meer informatie.
Het expliciet coderen IEnumerables van IGroupings kan snel tijdrovend worden. Schrijf dezelfde query en foreach lus veel handiger met behulp van var. Het var trefwoord wijzigt niet de typen van uw objecten; het geeft de compiler de opdracht om de typen af te afleiden. Wijzig het type studentQuery en de iteratievariabele group in var en voer de query opnieuw uit. In de binnenste foreach lus wordt de iteratievariabele nog steeds getypt als Studenten werkt de query net als voorheen. Wijzig de student iteratievariabele in var en voer de query opnieuw uit. U ziet dat u precies dezelfde resultaten krijgt.
IEnumerable<IGrouping<char, Student>> studentQuery =
from student in students
group student by student.Last[0];
foreach (IGrouping<char, Student> studentGroup in studentQuery)
{
Console.WriteLine(studentGroup.Key);
foreach (Student student in studentGroup)
{
Console.WriteLine($" {student.Last}, {student.First}");
}
}
Zie Impliciet getypte lokale variabelen voor meer informatie overvar.
De groepen rangschikt op basis van de sleutelwaarde
De groepen in de vorige query bevinden zich niet in alfabetische volgorde. U kunt een orderby component opgeven na de group component. Maar als u een orderby component wilt gebruiken, hebt u eerst een id nodig die fungeert als verwijzing naar de groepen die door de group component zijn gemaakt. U geeft de id op door gebruik te maken van het into trefwoord, als volgt:
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($" {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
Voer deze query uit en de groepen worden nu in alfabetische volgorde gesorteerd.
U kunt het let trefwoord gebruiken om een id te introduceren voor elk expressieresultaat in de query-expressie. Deze id kan handig zijn, zoals in het volgende voorbeeld. Het kan ook de prestaties verbeteren door de resultaten van een expressie op te slaan, zodat deze niet meerdere keren hoeft te worden berekend.
// 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
Zie het artikel over de let component voor meer informatie.
Methodesyntaxis gebruiken in een query-expressie
Zoals beschreven in querysyntaxis en methodesyntaxis in LINQ, kunnen sommige querybewerkingen alleen worden uitgedrukt met behulp van de syntaxis van de methode. Met de volgende code wordt de totale score voor elke Student score in de bronreeks berekend en wordt vervolgens de Average() methode aangeroepen voor de resultaten van die query om de gemiddelde score van de klasse te berekenen.
var studentQuery =
from student in students
let totalScore = student.Scores[0] + student.Scores[1] +
student.Scores[2] + student.Scores[3]
select totalScore;
double averageScore = studentQuery.Average();
Console.WriteLine($"Class average score = {averageScore}");
// Output:
// Class average score = 334.166666666667
Transformeren of projecteren in de select-klasse
Het is gebruikelijk dat een query een reeks produceert waarvan de elementen verschillen van de elementen in de bronreeksen. Verwijder of commentarieer uw vorige query- en uitvoeringslus en vervang deze door de volgende code. De query retourneert een reeks tekenreeksen (niet Students) en dit feit wordt weerspiegeld in de foreach lus.
IEnumerable<string> studentQuery =
from student in students
where student.Last == "Garcia"
select student.First;
Console.WriteLine("The Garcias in the class are:");
foreach (string s in studentQuery)
{
Console.WriteLine(s);
}
// Output:
// The Garcias in the class are:
// Cesar
// Debra
// Hugo
Code eerder in deze handleiding gaf aan dat de gemiddelde klassescore ongeveer 334 is. Als u een reeks wilt produceren waarvan Students een totale score heeft die hoger is dan het klasgemiddelde, samen met hun Student ID, kunt u een anoniem type in de select-instructie gebruiken.
var aboveAverageQuery =
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 aboveAverageQuery)
{
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