IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

8. diel - LINQ provideri, anonymné typy, radenie a zoskupovanie

V minulej lekcii, LINQ v C# .NET - Revolúcia v dopytovaní, sme si uviedli technológiu LINQ a vytvorili svoj prvý jednoduchý dotaz.

Dnes budeme v C# .NET tutoriále s technológiou LINQ pokračovať.

Provideri

Spomenuli sme si, že LINQ funguje vďaka tzv. providerom. To sú implementácie metód pre rôzne platformy, aby na nich bolo možné volať LINQ dotazy. Vymenujme si základné providery pre LINQ a ku každému si niečo málo povedzme.

Provideri v .NET

Niektoré providery dodáva Microsoft priamo v .NET frameworku, nás budú zaujímať najmä nasledujúce:

  • LINQ to Objects - Provider umožňuje klásť dotazy nad základnými kolekciami. Používali sme ho minule pre dopytovanie nad poľom, rovnako tak sa môžeme pýtať nad dátami v kolekcii List a ďalšími kolekciami z .NET. LINQ to Objects teda pracuje s dátami v operačnej pamäti.
  • LINQ to SQL/LINQ to Entities - Provider mapuje LINQ príkazy na SQL dotazy a umožňuje nám pracovať s MS-SQL databázou. Provider nám poskytuje tzv. ORM (Object-relation mapping, viď ďalšie diely kurzu). Práca s databázou je plne objektová, v kurzoch budeme často pracovať s providerom LINQ to Entities, LINQ to SQL je jeho predchodca. Linq to Entities je súčasťou tzv. Entity frameworku, čo je pomerne rozsiahla knižnica na prácu s relačnými (databázovými) dátami.
  • LINQ to XML - Provider umožňuje dotazy nad XML súborom. Rovnako ako pri LINQ to SQL ide o objektový prístup.

Provideri tretích strán

Keďže je samozrejme možné napísať si provider vlastný, mnoho hotových riešení existuje aj od tretích strán. Avšak, niektorí z nich nie sú príliš dobre podporovaní a je veľmi dobrý nápad držať sa skôr Microsoft technológií:

  • DbLinq - Najpoužívanejší provider tretej strany, ktorý umožňuje používať technológiu LINQ na databázach MySQL, SQLite, Oracle, Postgre SQL, Firebird a ďalších veľmi používaných databázových platformách.
  • LINQ to Excel - Provider umožňuje pracovať s Excelovou tabuľkou (Excelovým dokumentom) ako s databázou.
  • LINQ to JSON - Provider pre dotazovanie nad súbory formátu JSON.
  • LINQ to Amazon - LINQ to Amazon sa často uvádza ako ukážka providera tretej strany. Pomocou LINQ dotazov môžeme vyhľadávať v knihách, ktoré tento internetový obchod ponúka.

Vidíme, že providerov je dostatok a akonáhle vieme LINQ používať, nie je problém ho použiť takmer na všetko. V ďalších kurzoch sa budeme venovať LINQ to XML a LINQ to Entities.

Anonymné typy

Aby sme mohli vytvárať zložitejšie dotazy, presnejšie dostať z dotazu len tú časť dát, ktorá nás zaujíma, budeme používať tzv. anonymné typy. Anonymný typ sa chová ako inštancia triedy, ale žiadnu triedu na tento účel deklarovať nemusíme. Skúsme si to:

var anonym = new { FirstName="Anonymous", LastName="Very anonymous", Age="18" };
Console.WriteLine(anonym.FirstName);
Console.WriteLine(anonym.LastName);
Console.WriteLine(anonym.Age);

Výstup takého programu bude nasledujúci:

Konzolová aplikácia
Anonymous
Very anonymous
18

Vytvorili sme si anonymný dátový typ, ktorý má v sebe tri atribúty. Do nich sme rovno uložili hodnoty a celú štruktúru vložili do premennej typu var. Výsledný dátový typ je veľmi podivný a bez kľúčového slova var by sme takú premennú ťažko vytvorili.

Na čo je výhoda takýchto typov? V dotazoch si môžeme v select namapovať úplne, čo chceme. Majme kolekciu s autami a vodičmi. Budeme chcieť vybrať vždy ŠPZ auta a celé meno jeho vodiča pri červených autách. Vodič má na sebe vlastnosti FirstName a LastName, auto má na sebe vlastnosti Color, Driver a LicencePlate. Dotaz by vyzeral takto:

var query = from c in cars
            where (c.Color == "red")
            select new { c.LicencePlate, DriverName = c.Driver.FirstName + " " + c.Driver.LastName };

Aby nám dotaz mohol vrátiť takto zložitý výsledok, musíme si naň vytvoriť práve anonymný dátový typ. Výsledok dotazu bude teda kolekcia prvkov, kde každý prvok bude mať vlastnosti LicencePlate a DriverName. Všimnite si, že sme raz napísali len c.LicencePlate a druhýkrát DriverName = ... Ak chceme vložiť už nejakú existujúcu vlastnosť s rovnakým názvom, stačí uviesť iba tú. Ak chceme názov iný, musíme použiť PropertyName = value.

Pozor: Anonymnými typmi by sme mali šetriť rovnako ako napr. s kľúčovým slovom var. Opäť sa jedná o funkcionalitu vytvorenú na určité účely, hlavne pre LINQ dotazy. Nepoužívajte anonymné typy v bežnom programovaní namiesto tried, znižujete tak kvalitu zdrojového kódu aj výsledné aplikácie. Atribúty anonymných typov sú len na čítanie, presnejšie sa jedná o vlastnosti. Väčšinou sa chceme anonymným typom vyhnúť a radšej navrhneme dátovú vrstvu aplikácie tak, aby sme nemuseli písať príliš zložité dotazy. Použitím anonymných typov sa zbavujeme relácií medzi jednotlivými entitami, čo môže viesť v zložitejšej aplikácii k mnohým problémom. Lepšie by sme konkrétnu situáciu mohli riešiť tak, že autu vytvoríme vlastnosť DriverName a v select vyberieme celé auto, teda jednoducho select c. Meno vodiča si potom vytiahneme rovnako jednoducho, ako s anonymným typom. Zároveň pracujeme s celým autom vrátane všetkých väzieb a nie s nejakou neidentifikova­teľnou anonymnou entitou. Rovnako ale majú anonymné typy svoje miesto pre zložitejšie, najmä jednoúčelové dotazy a budú sa často objavovať v ukážkových dopytoch v týchto tutoriáloch.

Už vieme všetko potrebné na to, aby sme si ukázali syntax pre pokročilejšie dotazy.

Radenie a zoskupovanie

Minule sme si uviedli kľúčové slová from, where a select. Ukážme si ešte dvoch základných operátorov, než sa pustíme do podrobného popisu syntaxe LINQ.

orderby

Pokiaľ chceme výsledky dotazu zoradiť, použijeme operátor orderby:

var query = from u in users
            where (u.Age > 15)
            orderby u.FirstName
            select u.Age;
class User
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public int Age { get; private set; }

    public User(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }

    public override string ToString()
    {
        return FirstName + " " + LastName;
    }

}

Výstup:

Konzolová aplikácia
73
48
25
29
24

Ako už vieme, C# si tento dotaz vnútorne preloží na metódy:

var query = users.Where(u => u.Age > 15).OrderBy(u => u.FirstName).Select(u => u.Age);

Všetky klauzuly z LINQ majú svoje metódy, to bolo len pre upomenutie, ďalej už nebudem "metódovú" verziu pri ukážkach uvádzať.

Predvolený smer radenia je od najmenších hodnôt po najväčší (tu konkrétne radíme podľa mena užívateľa, teda od A do Z). Ak chceme radiť opačne, uvedieme kľúčové slovo descending:

var query = from u in users
            where (u.Age > 15)
            orderby u.FirstName descending
            select u.Age;
class User
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public int Age { get; private set; }

    public User(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }

    public override string ToString()
    {
        return FirstName + " " + LastName;
    }

}

Výstup:

Konzolová aplikácia
24
29
25
48
73

V pôvodnom príklade sme mohli použiť ascending, ale nie je to nutné. Pokiaľ ide o metódy, použije sa OrderByDescending().

Radiť môžeme aj podľa viacerých kritérií, jednoducho ich oddelíme čiarkou, tie prvé majú prednosť:

var query = from u in users
            where (u.Age > 15)
            orderby u.FirstName, u.LastName
            select u.Age;
class User
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public int Age { get; private set; }

    public User(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }

    public override string ToString()
    {
        return FirstName + " " + LastName;
    }

}

Výsledok:

Konzolová aplikácia
73
48
25
29
24

Tento dotaz si C# preloží na:

var query = users.Where(u => u.Age > 15).OrderBy(u => u.FirstName).ThenBy(u => u.LastName).Select(u => u.Age);

group - by (zoskupovanie)

V dotazoch často využívame zoskupovanie (grouping). Môžeme tak jednoducho prvky zoskupiť podľa určitých kritérií. Ukážme si príkad, ako by sme zoskupili užívateľov do skupín podľa ich veku:

var query = from u in users
            group u by u.Age into ageGroup
            select new { Age = ageGroup.Key, Users = ageGroup };

Čo že sme to urobili? Zoskupili sme používateľov podľa ich veku do ageGroup, čo je kolekcia, ktorá obsahuje vždy používateľov s rovnakým vekom. Je tam teda napr. skupina 24, skupina 25, 29 atď. Ďalej vyberáme, ako bude skupina vyzerať. Bude obsahovať vek, ten vezmeme z kľúča skupiny, ktorým je práve vek, pretože podľa neho zoskupujeme. Druhou vlastnosťou skupiny bude kolekcia používateľov, tam uložíme tú aktuálnu skupinu používateľov pre daný vek.

Prejdime k výpisu:

foreach (var group in query)
{
    Console.WriteLine(group.Age);
    foreach (var user in group.Users)
        Console.WriteLine(user.FirstName);
}

class User
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public int Age { get; private set; }

    public User(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }
}

Dotaz vyberie:

Konzolová aplikácia
25
Sophie
48
James
12
Omar
24
Timothy
73
Bill
29
Sylvia

Najprv proiterujeme všetky skupiny a pre každú skupinu vypíšeme jej vek a potom používateľa v nej obsiahnutej.

V nasledujúcom kvíze, Kvíz - Slovníky, množiny, front, zásobník v C# .NET Kolekcia, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
LINQ v C# .NET - Revolúcia v dopytovaní
Všetky články v sekcii
Kolekcia a LINQ v C# .NET
Preskočiť článok
(neodporúčame)
Kvíz - Slovníky, množiny, front, zásobník v C# .NET Kolekcia
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
1 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity