Integrovaný dotaz na jazyk - Language Integrated Query
Navrhl | společnost Microsoft |
---|---|
Vývojář | společnost Microsoft |
Psací disciplína | Silně napsaný |
webová stránka | dokumenty |
Hlavní implementace | |
Jazyky .NET ( C # , F # , VB.NET ) | |
Ovlivněno | |
SQL , Haskell |
Language Integrated Query ( LINQ , vyslovuje se „link“) je součást Microsoft .NET Framework, která přidává funkce nativního dotazování na data do jazyků .NET , původně vydaných jako hlavní součást .NET Framework 3.5 v roce 2007.
LINQ rozšiřuje jazyk přidáním výrazů dotazů , které jsou podobné příkazům SQL , a lze je použít k pohodlnému extrahování a zpracování dat z polí , vyčíslitelných tříd , dokumentů XML , relačních databází a zdrojů dat třetích stran. Další použití, která využívají výrazy dotazu jako obecný rámec pro čitelné skládání libovolných výpočtů, zahrnují konstrukci obslužných rutin událostí nebo monadické analyzátory . Rovněž definuje sadu názvů metod (tzv. Standardní operátory dotazů nebo operátory standardních sekvencí ) spolu s pravidly překladu používanými kompilátorem k překladu výrazů syntaxe dotazu do výrazů pomocí plynulého stylu (syntaxe metody od Microsoftu) s těmito názvy metod , výrazy lambda a anonymní typy . Mnoho konceptů, které LINQ představilo, bylo původně testováno ve výzkumném projektu Microsoftu Cω .
Porty LINQ existují pro PHP ( PHPLinq ), JavaScript ( linq.js ), strojopis ( linq.ts ), a ActionScript ( ActionLinq ), ačkoli žádný z nich striktně ekvivalentní LINQ v .NET inspiroval jazyky C #, F # a VB.NET (kde je součástí jazyka, nikoli externí knihovnou a kde často řeší širší škálu potřeb).
Architektura LINQ v .NET Framework
Standard Query Operator API
V následujícím textu jsou popisy operátorů založeny na aplikaci práce s kolekcemi. Mnoho operátorů bere jako argumenty další funkce. Tyto funkce mohou být dodávány ve formě pojmenované metody nebo anonymní funkce.
Sada operátorů dotazů definovaných LINQ je uživateli vystavena jako rozhraní API standardního dotazu (SQO) . Operátory dotazů podporované API jsou:
- Vybrat
Operátor Select provede projekci na kolekci a vybere zajímavé aspekty prvků. Uživatel dodává libovolnou funkci ve formě pojmenovaného nebo lambda výrazu , který promítá datové členy. Funkce je předána provozovateli jako delegát .
- Kde
Operátor Where umožňuje definici sady pravidel predikátů, která se vyhodnocují pro každý objekt v kolekci, zatímco objekty, které neodpovídají pravidlu, jsou odfiltrovány. Predikát se operátorovi dodává jako delegát.
- Vyberte mnoho
U mapování poskytovaného uživatelem z prvků kolekce do kolekcí se provádějí sémanticky dva kroky. Nejprve je každý prvek namapován na odpovídající kolekci. Za druhé, výsledek prvního kroku je zploštěn o jednu úroveň. Poznámka: Select a Where jsou oba implementovatelné z hlediska SelectMany, pokud jsou k dispozici singleton a prázdné kolekce. Díky výše uvedeným pravidlům překladu je pro poskytovatele LINQ povinné poskytovat další dva operátory.
- Součet / min. / Max. / Průměr
Tito operátoři volitelně berou funkci, která načte určitou číselnou hodnotu z každého prvku v kolekci a použije ji k vyhledání součtu, minimální, maximální nebo průměrné hodnoty všech prvků v kolekci. Přetížené verze nemají žádnou funkci a chovají se, jako by byla identita uvedena jako lambda.
- Agregát
Zobecněný součet / min / max. Tento operátor přebírá funkci, která určuje, jak jsou dvě hodnoty kombinovány, aby vytvořily přechodný nebo konečný výsledek. Volitelně lze zadat počáteční hodnotu, což umožňuje, aby byl výsledný typ agregace libovolný. Kromě toho lze dodat finalizační funkci, která vezme výsledek agregace na ještě jinou hodnotu.
- Připojte se / seskupte se
- Operátor Join provede vnitřní spojení na dvou kolekcích na základě odpovídajících klíčů pro objekty v každé kolekci. Trvá dvě funkce jako delegáti, jedna pro každou kolekci, kterou provede na každém objektu v kolekci, aby extrahovala klíč z objektu. Také si vezme dalšího delegáta, ve kterém uživatel určí, které datové prvky, ze dvou shodných prvků, by se měly použít k vytvoření výsledného objektu. Operátor GroupJoin provede skupinové připojení . Stejně jako operátor Select jsou výsledky spojení instancemi jiné třídy se všemi datovými členy obou typů zdrojových objektů nebo jejich podmnožinou.
- Take / TakeWhile
- Operátor Take vybere prvních n objektů z kolekce, zatímco operátor TakeWhile, který vezme predikát, vybere ty objekty, které odpovídají predikátu (zastaví se u prvního objektu, který mu neodpovídá).
- Přeskočit / Přeskočit Zatímco
- Skip a SkipWhile operátory jsou doplňky Take a TakeWhile - přeskočí prvních n objektů z kolekce nebo ty objekty, které odpovídají predikátu (pro případ SkipWhile).
- OfType
- Operátor OfType se používá k výběru prvků určitého typu.
- Concat
- Operátor Concat zřetězí dvě kolekce.
- OrderBy / ThenBy
- Operátor OrderBy se používá k určení primárního řazení prvků v kolekci podle nějakého klíče. Výchozí řazení je ve vzestupném pořadí, pro obrácení pořadí je třeba použít operátor OrderByDescending . ThenBy and ThenByDescending určuje následné řazení prvků. Funkce pro extrahování hodnoty klíče z objektu je zadána uživatelem jako delegát.
- Zvrátit
- Obrátit operátor obrátí kolekci.
- Skupina vytvořená
- Operátor GroupBy převezme funkci, která extrahuje hodnotu klíče a vrátí kolekci
IGrouping<Key, Values>
objektů, pro každou odlišnou hodnotu klíče. TytoIGrouping
objekty pak mohou být použity k vyjmenovat všechny objekty na určitou hodnotu klíče. - Odlišný
- Operátor Distinct odstraní duplikované instance objektu z kolekce. Přetížení operátoru přebírá objekt porovnávající rovnost, který definuje kritéria odlišnosti.
- Unie / Křižovatka / Mimo
- Tyto operátory se používají k provedení operace sjednocení , křižovatky a rozdílu u dvou sekvencí. Každý z nich má přetížení, které přebírá objekt porovnávající rovnost, který definuje kritéria pro rovnost prvků.
- SequenceEqual
- Operátor SequenceEqual určuje, zda jsou všechny prvky ve dvou kolekcích stejné a ve stejném pořadí.
- First / FirstOrDefault / Last / LastOrDefault
- Tito operátoři berou predikát. První operátor vrací první prvek, pro který predikát dává true, nebo pokud se nic neshoduje, vyvolá výjimku. Operátor FirstOrDefault je jako operátor First, kromě toho, že vrací výchozí hodnotu pro typ prvku (obvykle nulový odkaz) v případě, že nic neodpovídá predikátu. Poslední operátor načte poslední prvek, který odpovídá predikátu, nebo vyvolá výjimku v případě, že se nic neshoduje. LastOrDefault vrátí výchozí hodnotu prvku, pokud se nic neshoduje.
- Singl
- Single operátor vezme predikát a vrátí prvek, který odpovídá predikátu. Je vyvolána výjimka, pokud předikátu neodpovídá žádný nebo více než jeden prvek.
- SingleOrDefault
- SingleOrDefault operátor vezme predikát a vrátí prvek, který odpovídá predikátu. Pokud předikátu odpovídá více než jeden prvek, je vyvolána výjimka. Pokud žádný prvek neodpovídá predikátu, je vrácena výchozí hodnota.
- ElementAt
- Operátor ElementAt načte prvek v daném indexu v kolekci.
- Jakékoli / Všechny
- Operátor Any zkontroluje, zda v kolekci existují nějaké prvky odpovídající predikátu. Nevyberá prvek, ale vrátí hodnotu true, pokud je shodný alespoň jeden prvek. Vyvolání libovolného bez predikátu vrátí true, pokud kolekce není prázdná. Operátor All vrátí true, pokud všechny prvky odpovídají predikátu.
- Obsahuje
- Operátor Contains zkontroluje, zda kolekce obsahuje daný prvek.
- Počet
- Operátor Count počítá počet prvků v dané kolekci. Přetížení s predikátem počítá počet prvků odpovídajících predikátu.
Rozhraní Standard Query Operator API také určuje určité operátory, které převádějí kolekci na jiný typ:
- AsEnumerable: Staticky zadá kolekci jako
IEnumerable<T>
. - AsQueryable: Staticky zadá kolekci jako
IQueryable<T>
. - ToArray: Vytvoří pole
T[]
z kolekce. - ToList: Vytvoří
List<T>
z kolekce. - ToDictionary: Vytvoří
Dictionary<K, T>
z kolekce indexované klíčem K. Uživatelem poskytnutá projekční funkce extrahuje klíč z každého prvku. - ToLookup: Vytvoří
Lookup<K, T>
z kolekce indexované klíčem K. Uživatelem poskytnutá projekční funkce extrahuje klíč z každého prvku. - Cast: převede negenerickou
IEnumerable
kolekci na jednu tak,IEnumerable<T>
že každý prvek přetypuje na typT
. Alternativně převádí generikumIEnumerable<T>
na jiné generikumIEnumerable<R>
přetypováním každého prvku z typuT
na typR
. Vyvolá výjimku v jakémkoli prvku nelze přetypovat na uvedený typ. - OfType: převede negenerickou
IEnumerable
kolekci na jednu zIEnumerable<T>
. Alternativně převádí generikumIEnumerable<T>
na jiné generikumIEnumerable<R>
pokusem o seslání každého prvku z typuT
na typR
. V obou případech je zahrnuta pouze podmnožina prvků úspěšně přenesených do cílového typu. Nejsou vyvolány žádné výjimky.
Jazyková rozšíření
Zatímco LINQ je primárně implementován jako knihovna pro .NET Framework 3.5, definuje také volitelná jazyková rozšíření, díky nimž jsou dotazy prvotřídní jazykovou konstrukcí a poskytují syntaktický cukr pro psaní dotazů. Tato jazyková rozšíření byla původně implementována v C # 3.0, VB 9.0 , F # a Oxygene , další jazyky jako Nemerle oznámily předběžnou podporu. Mezi jazyková rozšíření patří:
- Syntaxe dotazu: Jazyk si může zvolit syntaxi dotazu, kterou nativně rozpozná. Tato jazyková klíčová slova musí být kompilátorem přeložena na příslušná volání metody LINQ.
- Implicitně zadané proměnné: Toto vylepšení umožňuje deklarovat proměnné bez určení jejich typů. Jazyky C # 3.0 a Oxygene je deklarují
var
klíčovým slovem. Ve VB9.0 dosahujeDim
klíčové slovo bez deklarace typu totéž. Takové objekty jsou stále silně psány ; pro tyto objekty kompilátor odvozuje typy proměnných pomocí odvození typu , což umožňuje specifikovat a definovat výsledky dotazů bez deklarace typu mezilehlých proměnných. - Anonymní typy : Anonymní typy umožňují, aby třídy, které obsahují pouze deklarace datových členů, byly odvozeny kompilátorem. To je užitečné pro operátory Select a Join, jejichž typy výsledků se mohou lišit od typů původních objektů. Kompilátor používá odvození typu k určení polí obsažených ve třídách a generuje pro tyto pole přístupové objekty a mutátory .
- Inicializátor objektu : Inicializátory objektu umožňují vytvoření a inicializaci objektu v jednom oboru, jak je vyžadováno pro operátory výběru a připojení.
- Lambda výrazy : Lambda výrazy umožňují predikáty a další projekční funkce psát inline se stručnou syntaxí a podporují úplné lexikální uzavření. Jsou zachyceny do parametrů jako delegáti nebo stromy výrazů v závislosti na poskytovateli dotazů.
Například v dotazu vyberte všechny objekty v kolekci s SomeProperty
méně než 10,
var results = from c in SomeCollection
where c.SomeProperty < 10
select new {c.SomeProperty, c.OtherProperty};
foreach (var result in results)
{
Console.WriteLine(result);
}
typy proměnných result , c a results all jsou odvozeny kompilátorem v souladu s podpisy nakonec použitých metod. Základ pro výběr metod tvoří výsledek dotazu bez výrazového překladu
var results =
SomeCollection
.Where(c => c.SomeProperty < 10)
.Select(c => new {c.SomeProperty, c.OtherProperty});
results.ForEach(x => {Console.WriteLine(x.ToString());})
Poskytovatelé LINQ
Specifikace C # 3.0 definuje vzor výrazu dotazu spolu s pravidly překladu z výrazu LINQ na výraz v podmnožině C # 3.0 bez výrazů LINQ. Takto definovaný překlad je ve skutečnosti netypizovaný, což kromě výrazů lambda, které lze interpretovat jako delegáty nebo stromy výrazů, umožňuje velkou míru flexibility pro knihovny, které chtějí vystavit části svého rozhraní jako klauzule výrazů LINQ. Například LINQ to Objects funguje na
IEnumerable<T>
s as delegáty, zatímco LINQ to SQL využívá stromy výrazů.
Stromy výrazů jsou jádrem mechanismu rozšiřitelnosti LINQ, kterým lze LINQ přizpůsobit pro mnoho zdrojů dat. Stromy výrazů jsou předány poskytovatelům LINQ, což jsou implementace specifické pro zdroj dat, které přizpůsobují dotazy LINQ pro použití se zdrojem dat. Pokud se tak rozhodnou, poskytovatelé LINQ analyzují stromy výrazů obsažené v dotazu, aby vygenerovaly základní části potřebné pro provedení dotazu. To mohou být fragmenty SQL nebo jakákoli jiná zcela odlišná reprezentace kódu jako další manipulovatelná data. LINQ přichází s poskytovateli LINQ pro kolekce objektů v paměti, databáze Microsoft SQL Server , datové sady ADO.NET a dokumenty XML. Tito různí poskytovatelé definují různé příchutě LINQ:
LINQ k objektům
Zprostředkovatel LINQ to Objects se používá pro kolekce v paměti pomocí stroje pro provádění lokálních dotazů LINQ. Kód vygenerovaný tímto poskytovatelem odkazuje na implementaci standardních operátorů dotazů, jak jsou definovány ve Sequence
vzoru, a umožňuje IEnumerable<T>
lokální dotazování kolekcí. Aktuální implementace LINQ to Objects provádí kontroly implementace rozhraní, které umožňují rychlé testy členství, počty a indexované vyhledávací operace, pokud jsou podporovány runtime typem IEnumerable.
LINQ to XML (dříve nazývané XLINQ)
Zprostředkovatel LINQ na XML převede dokument XML na kolekci XElement
objektů, které jsou poté dotazovány pomocí lokálního spouštěcího stroje, který je poskytován jako součást implementace standardního operátoru dotazu.
LINQ to SQL (dříve nazývané DLINQ)
Poskytovatel LINQ to SQL umožňuje LINQ použít k dotazování na databáze Microsoft SQL Serveru , včetně databází SQL Server Compact . Vzhledem k tomu, že data serveru SQL Server mohou být umístěna na vzdáleném serveru a protože SQL Server má svůj vlastní stroj dotazů, LINQ to SQL nepoužívá stroj dotazu LINQ. Místo toho převede dotaz LINQ na dotaz SQL, který se poté odešle na server SQL ke zpracování. Jelikož však SQL Server ukládá data jako relační data a LINQ pracuje s daty zapouzdřenými v objektech, musí být obě reprezentace mapovány jedna na druhou. Z tohoto důvodu LINQ to SQL také definuje rámec mapování. Mapování se provádí definováním tříd, které odpovídají tabulkám v databázi, a obsahuje všechny nebo podmnožinu sloupců v tabulce jako datové členy. Korespondence, spolu s dalšími atributy relačního modelu, jako jsou primární klíče , se zadávají pomocí atributů definovaných pomocí LINQ to SQL . Například,
[Table(Name="Customers")]
public class Customer
{
[Column(IsPrimaryKey = true)]
public int CustID;
[Column]
public string CustName;
}
Tato definice třídy se mapuje na pojmenovanou tabulku Customers
a dva datové členy odpovídají dvěma sloupcům. Před použitím LINQ to SQL musí být definovány třídy. Visual Studio 2008 obsahuje návrháře mapování, který lze použít k vytvoření mapování mezi datovými schématy v objektu a relační doménou. Může automaticky vytvořit odpovídající třídy ze schématu databáze a také umožnit ruční úpravy a vytvořit jiné zobrazení pomocí pouze podmnožiny tabulek nebo sloupců v tabulce.
Mapování je implementováno nástrojem, DataContext
který přebírá připojovací řetězec k serveru, a lze jej použít ke generování Table<T>
kde T je typ, na který bude mapována databázová tabulka. Table<T>
Zapouzdřuje data v tabulce a implementuje IQueryable<T>
rozhraní, takže je vytvořen výraz strom, který LINQ pro poskytovatele úchyty SQL. Převede dotaz na T-SQL a načte sadu výsledků z databázového serveru. Protože zpracování probíhá na databázovém serveru, nelze použít místní metody, které nejsou definovány jako součást výrazů lambda představujících predikáty. Může však použít uložené procedury na serveru. Všechny změny sady výsledků jsou sledovány a lze je odeslat zpět na databázový server.
LINQ to DataSets
Vzhledem k tomu, že poskytovatel LINQ to SQL (výše) funguje pouze s databázemi Microsoft SQL Server , aby bylo možné podporovat jakoukoli obecnou databázi, zahrnuje LINQ také LINQ to DataSets. Ke zpracování komunikace s databází používá ADO.NET. Jakmile jsou data v datových sadách ADO.NET, LINQ to DataSets spustí dotazy proti těmto datovým sadám.
Výkon
Neprofesionální uživatelé se mohou potýkat s jemnostmi ve funkcích a syntaxi LINQ to Objects . Naivní implementační vzory LINQ mohou vést ke katastrofickému snížení výkonu.
Výkon LINQ to XML a LINQ to SQL ve srovnání s ADO.NET závisí na případu použití.
PLINQ
Verze 4 rozhraní .NET obsahuje PLINQ nebo Parallel LINQ , paralelní spouštěcí stroj pro dotazy LINQ. Definuje ParallelQuery<T>
třídu. Jakákoli implementace IEnumerable<T>
rozhraní může využít výhod modulu PLINQ voláním AsParallel<T>(this IEnumerable<T>)
metody rozšíření definované ParallelEnumerable třídou v oboru názvů System.Linq .NET framework. Stroj PLINQ může souběžně spouštět části dotazu na více vláknech a poskytovat tak rychlejší výsledky.
Viz také
- Objektově-relační mapování (ORM)
- Neshoda objektově-relační impedance
- Seznam s porozuměním
- Líné hodnocení