Megosztás a következőn keresztül:


Standard lekérdezési operátorok áttekintése

A standard lekérdezési operátorok a LINQ-mintát alkotó kulcsszavak és metódusok. A C# nyelv határozza meg a linq lekérdezési kulcsszavakat , amelyeket a leggyakoribb lekérdezési kifejezéshez használ. A fordító lefordítja az ilyen kulcsszavakat használó kifejezéseket az egyenértékű metódushívásokra. A két forma szinonimák. A névtér részét System.Linq képező egyéb metódusok nem rendelkeznek egyenértékű lekérdezési kulcsszavakval. Ezekben az esetekben a metódus szintaxisát kell használnia. Ez a szakasz az összes lekérdezési operátor kulcsszót ismerteti. A futtatókörnyezet és más NuGet-csomagok további módszereket adnak hozzá a LINQ-lekérdezések minden kiadásához. A leggyakoribb metódusokat, beleértve azokat is, amelyek lekérdezési kulcsszóval egyenértékűek, ebben a szakaszban találja. A .NET-futtatókörnyezet által támogatott lekérdezési módszerek teljes listájáért tekintse meg az API dokumentációját System.Linq.Enumerable . Az itt tárgyalt módszerek mellett ez az osztály az adatforrások összefűzésére szolgáló módszereket is tartalmaz, és egyetlen értéket számít ki egy adatforrásból, például egy összeget, egy átlagot vagy más értéket.

Fontos

Ezek a minták adatforrást System.Collections.Generic.IEnumerable<T> használnak. A System.Linq.IQueryProvider alapú adatforrások a System.Linq.IQueryable<T> adatforrásokat és a kifejezésfákat használják. A kifejezésfák korlátozottan használhatják az engedélyezett C# szintaxist. Emellett minden adatforrás IQueryProvider , például az EF Core további korlátozásokat is alkalmazhat. Ellenőrizze az adatforrás dokumentációját.

Ezeknek a módszereknek a többsége szekvenciákon működik, ahol a sorozat olyan objektum, amelynek típusa implementálja az interfészt vagy az IEnumerable<T> interfészt IQueryable<T> . A standard lekérdezési operátorok olyan lekérdezési képességeket biztosítanak, mint a szűrés, a vetítés, az összesítés, a rendezés stb. Az egyes csoportokat alkotó metódusok a Enumerable és Queryable osztályokban definiált kiterjesztési tagok. Bővítménytagokként vannak bővítménytagok definiálva, ahol a fogadó típusa vagy a IEnumerable<T> vagy a IQueryable<T> típus, amelyen működnek.

A sorrendek és IEnumerable<T> a sorrendek különbsége IQueryable<T> határozza meg a lekérdezés futásidőben történő végrehajtását.

A IEnumerable<T>visszaadott számbavételi objektum rögzíti a metódusnak átadott argumentumokat. Az objektum számbavételekor a rendszer a lekérdezési operátor logikáját alkalmazza, és visszaadja a lekérdezési eredményeket.

A IQueryable<T>lekérdezés kifejezésfává lesz lefordítva. A kifejezésfa lefordítható natív lekérdezésre, ha az adatforrás optimalizálni tudja a lekérdezést. Az olyan kódtárak, mint az Entity Framework , a LINQ-lekérdezéseket natív SQL-lekérdezésekké fordítják le, amelyek az adatbázisban futnak.

Az alábbi példakód bemutatja, hogyan szerezhet be információkat egy sorozatról a szabványos lekérdezési operátorokkal.

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

Ahol lehetséges, az ebben a szakaszban szereplő lekérdezések szavak vagy számok sorozatát használják bemeneti forrásként. Az olyan lekérdezések esetében, ahol összetettebb kapcsolatokat használnak az objektumok között, a rendszer az alábbi, az iskolát modellező forrásokat használja:

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; }
}

Mindegyiknek Student van egy osztályszintje, egy elsődleges osztálya és egy sor pontszáma. Az Teacher rendelkezik egy City tulajdonsággal, amely azonosítja azt a campust, ahol a tanár órákat tart. A Department rendelkezik egy névvel és egy olyan személy hivatkozásával Teacher, aki az osztályvezető.

Az adatkészlet a forrásadattárban található.

A lekérdezési operátorok típusai

A szabványos lekérdezési operátorok eltérőek a végrehajtásuk időzítésében attól függően, hogy egy adott vagy egy értéksort adnak vissza. Azok a metódusok, amelyek egyszeri értéket adnak vissza (például Average és Sum) azonnal végrehajtanak. A sorozatot visszaadó metódusok elhalasztják a lekérdezés végrehajtását, és egy számbavehető objektumot adnak vissza. Az egyik lekérdezés kimeneti szekvenciáját használhatja egy másik lekérdezés bemeneti sorozataként. A lekérdezési metódusokat egyetlen lekérdezésben kell összekapcsolnia, amely lehetővé teszi a lekérdezések tetszőlegesen összetetté válását.

Lekérdezési operátorok

A LINQ-lekérdezések első lépése az adatforrás megadása. EGY LINQ-lekérdezésben a from záradék az első az adatforrás () és a students (student) bevezetéséhez.

//queryAllStudents is an IEnumerable<Student>
var queryAllStudents = from student in students
                        select student;

A tartományváltozó olyan, mint egy ciklus iterációs változója foreach , azzal a kivételrel, hogy egy lekérdezési kifejezésben nem történik tényleges iteráció. A lekérdezés végrehajtásakor a tartományváltozó hivatkozásként szolgál a függvény minden egymást követő elemére students. Mivel a fordító ki tudja következtetni a típust student, nem kell explicit módon megadnia. Egy záradékban let több tartományváltozót is bevezethet. További információért lásd a let kifejezést.

Megjegyzés

Az olyan nem általános adatforrások esetében, mint például ArrayList, a tartományváltozót explicit módon meg kell adni. További információ : Tömblista lekérdezése LINQ-val (C#) és záradékból.

Miután beszerezte az adatforrást, tetszőleges számú műveletet hajthat végre az adatforráson:

Lekérdezési kifejezés szintaxistáblája

Az alábbi táblázat azokat a szabványos lekérdezési operátorokat sorolja fel, amelyek egyenértékű lekérdezési kifejezési záradékokkal rendelkeznek.

Metódus C# lekérdezési kifejezés szintaxisa
Cast Használjon explicit módon beírt tartományváltozót:

from int i in numbers

(További információ: záradék.)
GroupBy group … by …

-vagy-

group … by … into …

(További információt a csoport záradékában talál.)
GroupJoin<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,IEnumerable<TInner>, TResult>) join … in … on … equals … into …

(További információ: join záradék.)
Join<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>) join … in … on … equals …

(További információ: join záradék.)
OrderBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>) orderby

(További információ: orderby záradék.)
OrderByDescending<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>) orderby … descending

(További információ: orderby záradék.)
Select select

(További információ: select utasítás.)
SelectMany Több from záradék.

(További információ: záradék.)
ThenBy<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>) orderby …, …

(További információ: orderby záradék.)
ThenByDescending<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>) orderby …, … descending

(További információ: orderby záradék.)
Where where

(További információ: hol található a záradék.)

Adatátalakítások a LINQ használatával

Language-Integrated lekérdezés (LINQ) nem csak az adatok beolvasásáról szól. Emellett hatékony eszköz az adatok átalakításához. A LINQ-lekérdezések használatával egy forrásütemezést használhat bemenetként, és számos módon módosíthatja egy új kimeneti sorozat létrehozásához. A sorrendet úgy módosíthatja, hogy nem módosítja az elemeket rendezéssel és csoportosítással. A LINQ-lekérdezések talán leghatékonyabb funkciója azonban az új típusok létrehozása. A kiválasztási záradék létrehoz egy kimeneti elemet egy bemeneti elemből. Egy bemeneti elem kimeneti elemgé alakításához használható:

  • Több bemeneti sorozat egyesítése egyetlen kimeneti sorozatba, amely új típusú.
  • Kimeneti sorozatok létrehozása, amelyek elemei a forrásütemezés egyes elemeinek csak egy vagy több tulajdonságából állnak.
  • Kimeneti sorozatok létrehozása, amelyek elemei a forrásadatokon végrehajtott műveletek eredményeiből állnak.
  • Kimeneti sorozatok létrehozása más formátumban. Az SQL-sorokból vagy szövegfájlokból származó adatokat például XML-fájllá alakíthatja.

Ezeket az átalakításokat különböző módokon kombinálhatja ugyanabban a lekérdezésben. Emellett használhatja egy lekérdezés kimeneti sorrendjét egy új lekérdezés bemeneti sorozataként. Az alábbi példa XML-elemekké alakítja a memóriában lévő adatstruktúrában lévő objektumokat.


// 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);

A kód a következő XML-kimenetet hozza létre:

<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>

További információ: XML-fák létrehozása C# nyelven (LINQ–XML).

Egy lekérdezés eredményeit használhatja adatforrásként egy későbbi lekérdezéshez. Ez a példa bemutatja, hogyan rendezheti egy illesztési művelet eredményeit. Ez a lekérdezés létrehoz egy csoportillesztést, majd rendezi a csoportokat az department elem alapján, amely továbbra is hatókörben van. A névtelen típusú inicializálón belül egy albekérdezés rendezi a sorozat összes egyező elemét students szerint.

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
*/

A metódusszintaxissal egyenértékű lekérdezés a következő kódban jelenik meg:

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}");
    }
}

Bár egy vagy több forrásszekvenciával együtt használhat egy orderby záradékot az illesztés előtt, általában nem javasoljuk. Előfordulhat, hogy egyes LINQ-szolgáltatók nem őrzik meg ezt a sorrendet a csatlakozás után. További információért lásd a(z) illesztési záradékot.

Lásd még