8. diel - LINQ provideri, anonymné typy, radenie a zoskupovanie
V minulej lekcii, LINQ v C # - revolúcia v dotazovanie , sme si uviedli technológiu LINQ a vytvorili svoj prvý jednoduchý dotaz. Dnes budeme v C# .NET tutoriálu s LINQ pokračovať.
Provideri
Spomenuli sme si, že LINQ funguje vďaka tzv. Tých dodávateľov. To sú implementácia metód pre rôzne platformy, aby na nich bolo možné volať LINQ dotazy. Vymenujme si základné providerov pre LINQ a ku každému si niečo málo povedzme.
Provideri v .NET:
Niektoré providermi dodáva Microsoft priamo v .NET frameworku, nás budú zaujímať najmä tieto:
- LINQ to Objects - Provider umožňuje klásť otázky nad
základnými kolekciami. Používali sme ho minule pre otázky nad poľom,
rovnako tak sa môžeme pýtať nad
List
ya ď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, pozri ď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 pre prácu s relačnými (databázovými) dátami.
- LINQ to XML - Provider umožňuje otázky nad XML súborom. Rovnako ako u LINQ to SQL sa jedná o objektový prístup.
Provideri tretích strán
Keďže je samozrejme možné napísať si provider vlastné, veľa hotových riešenie 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šie provider tretej strany, ktorý umožňuje používať technológiu LINQ na databázach MySQL, SQLite, Oracle, PostgreSQL, Firebird a ďalších veľmi používaných databázových platformách.
- LINQ to Excel - Provider umožňuje pracovať s excelovať 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 providerov 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 otázky, 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 { Jmeno="Anonym", Prijmeni="Anonymní", Vek="18" }; Console.WriteLine(anonym.Jmeno); Console.WriteLine(anonym.Prijmeni); Console.WriteLine(anonym.Vek);
Výstup takéhoto programu bude nasledujúci:
Vytvorili sme si anonymný dátový typ, ktorý má v sebe 3 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 čudný a bez kľúčového
slova var
by sme takú premennú ťažko vytvorili.
Na čo je výhoda takých typov? V dopytoch si môžeme v select
u namapovať úplne čo chceme. Majme kolekciu s autami a vodiči. Budeme
chcieť vybrať vždy ŠPZ auta a celé meno jeho vodiča u červených áut.
Vodič má na sebe vlastnosti Jmeno
a Prijmeni
, auto
má na sebe vlastnosti Barva
, Ridic
a
Spz
. Otázka by vyzeral takto:
var dotaz = from a in auta where (a.Barva == "cervena") select new { a.Spz, JmenoRidice = a.Ridic.Jmeno + " " + a.Ridic.Prijmeni };
Aby nám dotaz mohol vrátiť takto zložitý výsledok, musíme si na neho
vytvoriť práve anonymný dátový typ. Výsledok dotazu bude teda kolekcie
prvkov, kde každý prvok bude mať vlastnosti Spz
a
JmenoRidice
. Všimnite si, že sme raz napísali len
a.Spz
a druhýkrát JmenoRidice = ....
Ak chceme
vložiť už nejakú existujúcu vlastnosť s rovnakým názvom, stačí uviesť
len tú. Ak chceme názov iný, musíme použiť
NazevVlastnosti = hodnota
.
Pozor: anonymným typy by sme mali šetriť rovnako ako
napr. S kľúčovým slovom var
. Opäť sa jedná o funkcionalitu
vytvorenú pre určité účely, najmä do LINQ dotazov. Nepoužívajte
anonymné typy v bežnom programovaní namiesto tried, znižujete tak kvalitu
zdrojového kódu aj výslednej aplikácie. Atribúty anonymných typov
sú iba na čítanie, presnejšie sa jedná o
vlastnosti. Väčšinou sa chceme anonymným typom vyhnúť a
radšej navrhneme datavou vrstvu aplikácie tak, aby sme nemuseli sme písať
príliš zložité otázky. Použitím anonymných typov sa zbavujeme relácií
medzi jednotlivými entitami, čo môže viesť vo zložitejšie aplikácii k
mnohým problémom. Lepšie by sme konkrétnu situáciu mohli riešiť tak, že
autu vytvoríme vlastnosť JmenoRidice
a v select
u
vyberieme celé auto, teda jednoducho select a
. Meno vodiča si
potom vytiahne 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 nezistiteľnú
anonymný entitou. Rovnako tak ale majú anonymné typy svoje miesto pre
zložitejšie, najmä jednoúčelové otázky a budú sa často objavovať v
ukážkových dotazoch v týchto tutoriáloch.
Už vieme všetko potrebné k tomu, aby sme si ukázali syntax pokročilejších otázok.
Radenie a zoskupovanie
Minule sme si uviedli kľúčové slová from
,
where
a select
. Ukážme si ešte 2 základné
operátormi, než sa pustíme do podrobného opisu syntaxe LINQ.
Orderby
Ak chceme výsledky dotazu zoradiť, použijeme operátor
orderby
:
var dotaz = from u in uzivatele where (u.Vek > 15) orderby u.Jmeno select u.Vek;
Ako už vieme, C# si tento dotaz vnútorne preloží na metódy:
var dotaz = uzivatele.Where(u => u.Vek > 15).OrderBy(u => u.Jmeno).Select(u => u.Vek);
Všetky klauzuly z LINQ majú svoje metódy, to bolo len pre upomenutý, ďalej už nebudem "Metodova" verziu u ukážok uvádzať.
Predvolené smer radenie je od najmenších hodnôt po najväčšie (tu
konkrétne radíme podľa mena používateľa, teda od A do Z). Ak chceme radiť
opačne, uvedieme kľúčové slovo descending
:
var dotaz = from u in uzivatele where (u.Vek > 15) orderby u.Jmeno descending select u.Vek;
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, tá prvá majú prednosť:
var dotaz = from u in uzivatele where (u.Vek > 15) orderby u.Jmeno, u.Prijmeni select u.Vek;
Tento dotaz si C# preloží na:
var dotaz = uzivatele.Where(u => u.Vek > 15).OrderBy(u => u.Jmeno).ThenBy(u => u.Prijmeni).Select(u => u.Vek);
Group (zoskupovanie)
V otázkach často využívame zoskupovanie (grouping). Môžeme tak jednoducho prvky zoskupiť podľa určitých kritérií. Ukážme si příkad ako by sme zoskupili užívateľa do skupín podľa ich veku:
var dotaz = from u in uzivatele group u by u.Vek into vekovaSkupina select new { Vek = vekovaSkupina.Key, Uzivatele = vekovaSkupina };
Čo že sme to urobili? Zoskupili sme užívateľa podľa ich veku do
vekovaSkupina
, čo je kolekcia, ktorá obsahuje vždy užívateľa
s rovnakým vekom. Je tam teda napr, skupina 15
, skupina
16
, 17
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 zoskupujú. Druhou vlastnosťou skupiny bude kolekcia
užívateľov, tam uložíme tú aktuálnu skupinu používateľov pre daný
vek.
Prejdime k výpisu:
foreach (var skupina in dotaz) { Console.WriteLine(skupina.Vek); foreach (var uzivatel in skupina.Uzivatele) Console.WriteLine(uzivatel.Jmeno); }
Najprv proiterujeme všetky skupiny a pre každú skupiny vypíšeme jej vek a potom používateľa v nej obsiahnuté.
V budúcej lekcii, LINQ operátormi 1 , budeme pokračovať v opise syntaxe LINQ, pozrieme sa na otázky cez viac kolekcií.