Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Vanliga frågeoperatorer är nyckelord och metoder som utgör LINQ-mönstret. C#-språket definierar LINQ-frågenyckelord som du använder för det vanligaste frågeuttrycket. Kompilatorn översätter uttryck med hjälp av dessa nyckelord till motsvarande metodanrop. De två formerna är synonyma. Andra metoder som ingår i System.Linq namnområdet har inte motsvarande frågenyckelord. I sådana fall måste du använda metodsyntaxen. Det här avsnittet beskriver alla nyckelord för frågeoperatorn. Körtiden och andra NuGet-paket lägger vid varje släpp till fler metoder som är utformade för att fungera med LINQ-frågor. De vanligaste metoderna, inklusive de som har frågenyckelordsekvivalenter, beskrivs i det här avsnittet. En fullständig lista över frågemetoder som stöds av .NET Runtime finns i API-dokumentationen System.Linq.Enumerable . Förutom de metoder som beskrivs här innehåller den här klassen metoder för att sammanfoga datakällor, beräkna ett enda värde från en datakälla, till exempel en summa, ett genomsnitt eller ett annat värde.
Viktigt!
Dessa exempel använder en System.Collections.Generic.IEnumerable<T> datakälla. Datakällor baserade på System.Linq.IQueryProvider använder System.Linq.IQueryable<T> datakällor och uttrycksträd. Uttrycksträd har begränsningar för den tillåtna C#-syntaxen. Dessutom kan varje IQueryProvider datakälla, till exempel EF Core , införa fler begränsningar. Kontrollera dokumentationen för din datakälla.
De flesta av dessa metoder fungerar på sekvenser, där en sekvens är ett objekt vars typ implementerar IEnumerable<T> gränssnittet eller IQueryable<T> gränssnittet. Standardfrågeoperatorerna tillhandahåller frågefunktioner som filtrering, projektion, aggregering, sortering med mera. De metoder som utgör varje uppsättning är tilläggsmedlemmar som definierats i klasserna Enumerable och Queryable . De definieras som tilläggsmedlemmar där mottagartypen är antingen IEnumerable<T> eller IQueryable<T>, den typ de arbetar med.
Skillnaden mellan IEnumerable<T>- och IQueryable<T>-sekvenser avgör hur förfrågan utförs vid körning.
För IEnumerable<T>samlar det returnerade uppräkningsbara objektet in argumenten som skickades till metoden. När objektet räknas upp används logiken för frågeoperatorn och frågeresultatet returneras.
För IQueryable<T>översätts frågan till ett uttrycksträd. Uttrycksträdet kan översättas till en intern fråga när datakällan kan optimera frågan. Bibliotek som Entity Framework översätter LINQ-frågor till interna SQL-frågor som körs i databasen.
I följande kodexempel visas hur du kan använda standardfrågeoperatorerna för att hämta information om en sekvens.
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
När det är möjligt använder frågorna i det här avsnittet en sekvens med ord eller siffror som indatakälla. För frågor där mer komplicerade relationer mellan objekt används används följande källor som modellerar en skola:
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; }
}
Varje Student har en betygsnivå, en primär avdelning och en serie resultat. En Teacher har också en City egenskap som identifierar det campus där läraren har klasser. A Department har ett namn och en referens till en Teacher som fungerar som avdelningschef.
Du hittar datauppsättningen i källdatabasen.
Typer av frågeoperatorer
Standardfrågeoperatorerna skiljer sig åt i tidpunkten för körningen, beroende på om de returnerar ett singleton-värde eller en sekvens med värden. De metoder som returnerar ett singleton-värde (till exempel Average och Sum) körs omedelbart. Metoder som returnerar en sekvens skjuter upp frågekörningen och returnerar ett uppräkningsbart objekt. Du kan använda utdatasekvensen för en fråga som indatasekvens till en annan fråga. Du kedjar ihop frågemetoder i en fråga, vilket gör att frågor blir godtyckligt komplexa.
Frågeoperatorer
I en LINQ-fråga är det första steget att ange datakällan. I en LINQ-fråga from kommer satsen först för att introducera datakällan (students) och intervallvariabeln (student).
//queryAllStudents is an IEnumerable<Student>
var queryAllStudents = from student in students
select student;
Intervallvariabeln liknar iterationsvariabeln i en foreach loop förutom att ingen faktisk iteration sker i ett frågeuttryck. När frågan körs fungerar intervallvariabeln som en referens till varje efterföljande element i students. Eftersom kompilatorn kan härleda typen av studentbehöver du inte ange den explicit. Du kan introducera fler intervallvariabler i en let sats. För mer information, se let-satsen.
Anmärkning
För icke-generiska datakällor som ArrayList, måste du uttryckligen ange intervallvariabeln. För mer information, se Hur man gör frågor mot en ArrayList med LINQ (C#) och from-klausul.
När du har hämtat en datakälla kan du utföra valfritt antal åtgärder på datakällan:
-
Filtrera data med nyckelordet
where. -
Sortera data med hjälp av
orderbyoch valfrittdescendingnyckelord. -
Gruppera data med nyckelorden
groupoch eventuelltinto. -
Sammanfoga data med nyckelordet
join. -
Projektdata med nyckelordet
select.
Syntaxtabell för frågeuttryck
I följande tabell visas de standardfrågasoperatorer som har motsvarande frågeuttryckssatser.
Datatransformeringar med LINQ
Language-Integrated Query (LINQ) handlar inte bara om att hämta data. Det är också ett kraftfullt verktyg för att transformera data. Genom att använda en LINQ-fråga kan du använda en källsekvens som indata och ändra den på många sätt för att skapa en ny utdatasekvens. Du kan ändra själva sekvensen utan att ändra själva elementen genom att sortera och gruppera. Men den kanske mest kraftfulla funktionen i LINQ-frågor är möjligheten att skapa nya typer. Select-satsen skapar ett utdataelement från ett indataelement. Du använder det för att omvandla ett indataelement till ett utdataelement:
- Sammanfoga flera indatasekvenser till en enda utdatasekvens som har en ny typ.
- Skapa utdatasekvenser vars element endast består av en eller flera egenskaper för varje element i källsekvensen.
- Skapa utdatasekvenser vars element består av resultatet av åtgärder som utförs på källdata.
- Skapa utdatasekvenser i ett annat format. Du kan till exempel omvandla data från SQL-rader eller textfiler till XML.
Du kombinerar dessa transformeringar på olika sätt i samma fråga. Dessutom kan du använda utdatasekvensen för en fråga som indatasekvens för en ny fråga. I följande exempel transformeras objekt i en minnesintern datastruktur till XML-element.
// 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);
Koden genererar följande XML-utdata:
<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>
Mer information finns i Skapa XML-träd i C# (LINQ till XML).
Du kan använda resultatet av en fråga som datakälla för en efterföljande fråga. Det här exemplet visar hur du beställer resultatet av en kopplingsåtgärd. Den här frågan skapar en gruppkoppling och sorterar sedan grupperna baserat på elementet department , som fortfarande finns i omfånget. I den anonyma typinitieraren beställer en underfråga alla matchande element från sekvensen students .
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
*/
Motsvarande fråga med metodsyntax visas i följande kod:
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}");
}
}
Även om du kan använda en orderby sats med en eller flera av källsekvenserna före kopplingen rekommenderar vi vanligtvis inte det. Vissa LINQ-leverantörer kanske inte bevarar beställningen efter kopplingen. Mer information finns i kopplingssatsen.