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.
De standaardqueryoperators zijn de trefwoorden en methoden die het LINQ-patroon vormen. De C#-taal definieert LINQ-querytrefwoorden die u gebruikt voor de meest voorkomende query-expressie. De compiler vertaalt expressies met behulp van deze trefwoorden naar de equivalente methode-aanroepen. De twee vormen zijn synoniem. Andere methoden die deel uitmaken van de System.Linq naamruimte hebben geen equivalente querytrefwoorden. In die gevallen moet u de syntaxis van de methode gebruiken. In deze sectie worden alle trefwoorden van de queryoperator behandeld. De runtime en andere NuGet-pakketten voegen meer methoden toe die zijn ontworpen om elke release te werken met LINQ-query's. In deze sectie worden de meest voorkomende methoden behandeld, waaronder methoden met trefwoordequivalenten voor query's. Zie de API-documentatie voor de System.Linq.Enumerable volledige lijst met querymethoden die worden ondersteund door .NET Runtime. Naast de methoden die hier worden behandeld, bevat deze klasse methoden voor het samenvoegen van gegevensbronnen, het berekenen van één waarde uit een gegevensbron, zoals een som, gemiddelde of andere waarde.
Belangrijk
In deze voorbeelden wordt een System.Collections.Generic.IEnumerable<T> gegevensbron gebruikt. Gegevensbronnen gebaseerd op System.Linq.IQueryProvider maken gebruik van System.Linq.IQueryable<T> gegevensbronnen en expressiebomen. Expressiestructuren hebben beperkingen voor de toegestane C#-syntaxis. Bovendien kan elke IQueryProvider
gegevensbron, zoals EF Core , meer beperkingen opleggen. Raadpleeg de documentatie voor uw gegevensbron.
De meeste van deze methoden werken op reeksen, waarbij een reeks een object is waarvan het type de IEnumerable<T> interface of de IQueryable<T> interface implementeert. De standaardqueryoperators bieden querymogelijkheden, waaronder filteren, projectie, aggregatie, sorteren en meer. De methoden waaruit elke set bestaat, zijn respectievelijk statische leden van de Enumerable en Queryable klassen. Ze worden gedefinieerd als uitbreidingsmethoden van het type waarop ze werken.
Het onderscheid tussen IEnumerable<T> en IQueryable<T> reeksen bepaalt hoe de query tijdens runtime wordt uitgevoerd.
Voor IEnumerable<T>
worden de argumenten die aan de methode zijn doorgegeven vastgelegd in het geretourneerde enumerate-object. Wanneer dat object is geïnventariseerd, wordt de logica van de queryoperator gebruikt en worden de queryresultaten geretourneerd.
De IQueryable<T>
query wordt omgezet in een expressiestructuur. De expressiestructuur kan worden vertaald naar een systeemeigen query wanneer de gegevensbron de query kan optimaliseren. Bibliotheken zoals Entity Framework vertalen LINQ-query's naar systeemeigen SQL-query's die worden uitgevoerd in de database.
In het volgende codevoorbeeld ziet u hoe de standaardqueryoperators kunnen worden gebruikt om informatie over een reeks te verkrijgen.
string sentence = "the quick brown fox jumps over the lazy dog";
// Split the string into individual words to create a collection.
string[] words = sentence.Split(' ');
// Using query expression syntax.
var query = from word in words
group word.ToUpper() by word.Length into gr
orderby gr.Key
select new { Length = gr.Key, Words = gr };
// Using method-based query syntax.
var query2 = words.
GroupBy(w => w.Length, w => w.ToUpper()).
Select(g => new { Length = g.Key, Words = g }).
OrderBy(o => o.Length);
foreach (var obj in query)
{
Console.WriteLine($"Words of length {obj.Length}:");
foreach (string word in obj.Words)
Console.WriteLine(word);
}
// This code example produces the following output:
//
// Words of length 3:
// THE
// FOX
// THE
// DOG
// Words of length 4:
// OVER
// LAZY
// Words of length 5:
// QUICK
// BROWN
// JUMPS
Waar mogelijk gebruiken de query's in deze sectie een reeks woorden of getallen als invoerbron. Voor query's waarbij complexere relaties tussen objecten worden gebruikt, worden de volgende bronnen gebruikt die een school modelleren:
public enum GradeLevel
{
FirstYear = 1,
SecondYear,
ThirdYear,
FourthYear
};
public class Student
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required int ID { get; init; }
public required GradeLevel Year { get; init; }
public required List<int> Scores { get; init; }
public required int DepartmentID { get; init; }
}
public class Teacher
{
public required string First { get; init; }
public required string Last { get; init; }
public required int ID { get; init; }
public required string City { get; init; }
}
public class Department
{
public required string Name { get; init; }
public int ID { get; init; }
public required int TeacherID { get; init; }
}
Elk Student
heeft een cijferniveau, een primaire afdeling en een reeks scores. Een Teacher
heeft ook een City
eigenschap die de campus identificeert waar de docent klassen heeft. A Department
heeft een naam en een verwijzing naar een Teacher
persoon die als afdelingshoofd fungeert.
U vindt de gegevensset in de bronopslagplaats.
Soorten queryoperators
De standaardqueryoperators verschillen in de timing van de uitvoering, afhankelijk van of ze een singleton-waarde of een reeks waarden retourneren. Deze methoden die een singleton-waarde (zoals Average en Sum) retourneren, worden onmiddellijk uitgevoerd. Methoden die een reeks retourneren, stellen de uitvoering van de query uit en retourneren een opsommingsobject. U kunt de uitvoervolgorde van één query gebruiken als invoerreeks voor een andere query. Aanroepen naar querymethoden kunnen in één query worden gekoppeld, waardoor query's willekeurig complex kunnen worden.
Queryoperators
In een LINQ-query moet u eerst de gegevensbron opgeven. In een LINQ-query komt de from
component eerst voor het introduceren van de gegevensbron (students
) en de bereikvariabele (student
).
//queryAllStudents is an IEnumerable<Student>
var queryAllStudents = from student in students
select student;
De bereikvariabele is net als de iteratievariabele in een foreach
lus, behalve dat er geen werkelijke iteratie plaatsvindt in een query-expressie. Wanneer de query wordt uitgevoerd, fungeert de bereikvariabele als verwijzing naar elk opeenvolgend element in students
. Omdat de compiler het type student
kan afleiden, hoeft u deze niet expliciet op te geven. U kunt meer bereikvariabelen in een let
clausule introduceren. Voor meer informatie, zie let-clausule.
Notitie
Voor niet-algemene gegevensbronnen, zoals ArrayList, moet de bereikvariabele expliciet worden getypt. Zie Hoe een ArrayList opvragen met LINQ (C#) en from-clausule voor meer informatie.
Zodra u een gegevensbron hebt verkregen, kunt u een willekeurig aantal bewerkingen uitvoeren op die gegevensbron:
-
Gegevens filteren met behulp van het
where
trefwoord. -
Bestel gegevens met behulp van de
orderby
en optioneeldescending
trefwoorden. -
Groepeer gegevens met behulp van de
group
en optioneelinto
trefwoorden. -
Voeg gegevens toe met behulp van het
join
trefwoord. -
Projectgegevens met behulp van het
select
trefwoord.
Syntaxistabel voor query-expressies
De volgende tabel bevat de standaardqueryoperators met equivalente queryexpressieclausules.
Gegevenstransformaties met LINQ
Language-Integrated Query (LINQ) gaat niet alleen over het ophalen van gegevens. Het is ook een krachtig hulpmiddel voor het transformeren van gegevens. Met behulp van een LINQ-query kunt u een bronreeks als invoer gebruiken en deze op veel manieren wijzigen om een nieuwe uitvoerreeks te maken. U kunt de volgorde zelf wijzigen zonder de elementen zelf te wijzigen door te sorteren en groeperen. Maar misschien is de krachtigste functie van LINQ-query's de mogelijkheid om nieuwe typen te maken. Met de select-component maakt u een uitvoerelement van een invoerelement. U gebruikt dit om een invoerelement te transformeren in een uitvoerelement:
- Voeg meerdere invoerreeksen samen in één uitvoerreeks met een nieuw type.
- Maak uitvoerreeksen waarvan de elementen uit slechts één of meerdere eigenschappen van elk element in de bronreeks bestaan.
- Uitvoerreeksen maken waarvan de elementen bestaan uit de resultaten van bewerkingen die worden uitgevoerd op de brongegevens.
- Maak uitvoerreeksen in een andere indeling. U kunt bijvoorbeeld gegevens van SQL-rijen of tekstbestanden transformeren in XML.
Deze transformaties kunnen op verschillende manieren in dezelfde query worden gecombineerd. Bovendien kan de uitvoervolgorde van één query worden gebruikt als invoerreeks voor een nieuwe query. In het volgende voorbeeld worden objecten in een gegevensstructuur in het geheugen omgezet in XML-elementen.
// Create the query.
var studentsToXML = new XElement("Root",
from student in students
let scores = string.Join(",", student.Scores)
select new XElement("student",
new XElement("First", student.FirstName),
new XElement("Last", student.LastName),
new XElement("Scores", scores)
) // end "student"
); // end "Root"
// Execute the query.
Console.WriteLine(studentsToXML);
De code produceert de volgende XML-uitvoer:
<Root>
<student>
<First>Svetlana</First>
<Last>Omelchenko</Last>
<Scores>97,90,73,54</Scores>
</student>
<student>
<First>Claire</First>
<Last>O'Donnell</Last>
<Scores>56,78,95,95</Scores>
</student>
...
<student>
<First>Max</First>
<Last>Lindgren</Last>
<Scores>86,88,96,63</Scores>
</student>
<student>
<First>Arina</First>
<Last>Ivanova</Last>
<Scores>93,63,70,80</Scores>
</student>
</Root>
Zie XML-structuren maken in C# (LINQ naar XML) voor meer informatie.
U kunt de resultaten van één query gebruiken als de gegevensbron voor een volgende query. In dit voorbeeld ziet u hoe u de resultaten van een joinbewerking kunt ordenen. Met deze query maakt u een groepsdeelname en sorteert u vervolgens de groepen op basis van het categorieelement, dat nog steeds binnen het bereik valt. In de initialisatiefunctie van het anonieme type worden alle overeenkomende elementen uit de productenreeks door een subquery georderd.
var orderedQuery = from department in departments
join student in students on department.ID equals student.DepartmentID into studentGroup
orderby department.Name
select new
{
DepartmentName = department.Name,
Students = from student in studentGroup
orderby student.LastName
select student
};
foreach (var departmentList in orderedQuery)
{
Console.WriteLine(departmentList.DepartmentName);
foreach (var student in departmentList.Students)
{
Console.WriteLine($" {student.LastName,-10} {student.FirstName,-10}");
}
}
/* Output:
Chemistry
Balzan Josephine
Fakhouri Fadi
Popov Innocenty
Seleznyova Sofiya
Vella Carmen
Economics
Adams Terry
Adaobi Izuchukwu
Berggren Jeanette
Garcia Cesar
Ifeoma Nwanneka
Jamuike Ifeanacho
Larsson Naima
Svensson Noel
Ugomma Ifunanya
Engineering
Axelsson Erik
Berg Veronika
Engström Nancy
Hicks Cassie
Keever Bruce
Micallef Nicholas
Mortensen Sven
Nilsson Erna
Tucker Michael
Yermolayeva Anna
English
Andersson Sarah
Feng Hanying
Ivanova Arina
Jakobsson Jesper
Jensen Christiane
Johansson Mark
Kolpakova Nadezhda
Omelchenko Svetlana
Urquhart Donald
Mathematics
Frost Gaby
Garcia Hugo
Hedlund Anna
Kovaleva Katerina
Lindgren Max
Maslova Evgeniya
Olsson Ruth
Sammut Maria
Sazonova Anastasiya
Physics
Åkesson Sami
Edwards Amy E.
Falzon John
Garcia Debra
Hansson Sanna
Mattsson Martina
Richardson Don
Zabokritski Eugene
*/
De equivalente query met behulp van de methodesyntaxis wordt weergegeven in de volgende code:
var orderedQuery = departments
.GroupJoin(students, department => department.ID, student => student.DepartmentID,
(department, studentGroup) => new
{
DepartmentName = department.Name,
Students = studentGroup.OrderBy(student => student.LastName)
})
.OrderBy(department => department.DepartmentName);
foreach (var departmentList in orderedQuery)
{
Console.WriteLine(departmentList.DepartmentName);
foreach (var student in departmentList.Students)
{
Console.WriteLine($" {student.LastName,-10} {student.FirstName,-10}");
}
}
Hoewel u vóór de join een orderby
component met een of meer bronreeksen kunt gebruiken, wordt dit over het algemeen niet aanbevolen. Sommige LINQ-providers behouden die volgorde mogelijk niet na de join. Voor meer informatie, zie join-clausule.