Ce este și ce face LINQ în C#

Dacă ești programator C# LINQ e unul din cele mai importante aspecte pe care trebuie să le stăpânești.

Hai să vedem ce este și de ce avem nevoie de asta.

LINQ vine de la Language Integrated Query sau “interogare integrată în limbaj” și e o caracteristică a limbajului C# ce permite interogarea a diferite surse de date folosind aceeași sintaxă.

De ce se spune că interogarea e integrată în limbaj?

Înainte să-ți explic asta, ce vreau să mai știi e că termenul de “interogare” e folosit pentru citirea unui set de date dintr-o bază sau sursă de date.

Interogarea se poate face atât de către un programator, cât și de un sistem, o aplicație care interacționează cu baza de date pentru a citi date.

În majoritatea cazurilor, limbajele folosite pentru a face o “interogare” se numesc “query language”.

SQL, sau Structured Query Language e limbajul pe care cele mai multe baze de date relaționale îl acceptă pentru a executa interogări.

Prin “interogare” ne referim la operațiuni de filtrare, sortare și grupare a înregistrărilor dintr-o sursă de date.

Se spune că în cazul LINQ, interogarea este integrată în limbaj, pentru că limbajul folosit e foarte bine integrat în limbajul de programare și de asemenea verificat la compilare.

Problema

Sistemele software complexe, de multe ori nu folosesc doar baze de date ca surse de date.

Se poate întâmpla ca aplicațiile să importe diferite seturi de date folosind fișiere XML, de exemplu.

Iar interogarea acestui gen de fișiere se face cu un limbaj denumit XQuery.

Traversarea și filtrarea elementelor dintr-un document HTML, de exemplu, se face folosind XPath.

Toate aceste limbaje nu beneficiază de un compilator și sunt foarte predispuse la erori în momentul în care se scriu interogările.

Aici vine LINQ în ajutorul nostru.

LINQ ne oferă posibilitatea să folosim aceleași metode în cod pentru interogarea unei surse de date, indiferent de natura acesteia.

Cu LINQ putem să scriem codul pentru filtrarea unui set de date în același mod, indiferent că la celălalt capăt al firului se află o bază de date relațională, o bază de date non-relațională, un fișier pe disc, cum ar fi XML sau o colecție stocată în memorie.

LINQ reprezintă o colecție de metode de tip extensie (extension methods), pe care le putem apela indiferent care este sursa datelor.

Mai mult decât atât, pentru că ceea ce scrii cu LINQ e tot cod de C#, asta înseamnă că toate interogările sunt de asemenea și compilate, spre deosebire oricare limbaj dedicat pentru asta (cum ar fi SQL).

Asta înseamnă că multe din potențialele defecte sunt eliminate din start.

Tipuri de sintaxă

LINQ oferă 2 tipuri de sintaxă:

  • Sintaxă de tip interogare (Query Syntax)
  • Sintaxă de tip metodă (Method Syntax)

Deși poți face absolut același lucru cu ambele variante, ele sunt totodată și foarte diferite ca sintax.

Sintaxă de tip interogare (Query Syntax)

Sintaxa de tip interogare, care se bazează pe câteva cuvinte cheie dedicate și care de asemenea seamănă foarte mult cu SQL.

Uite cum arată filtrarea unei liste, de exemplu:

var users = new List<User>();
var adults = 
	from user in users 
	where user.Age > 18
	select user;

Șablonul folosit în această sintaxă este: “from [variabilă] in [sursă de date] where [condiție] select [variabilă]”.

from, in, where și select sunt toate cuvinte cheie specifice sintaxei de tip interogare.

Am scris codul acestei interogări într-o structură verticală, cu câte o instrucțiune pe fiecare rând, pentru că e mai ușor de citit și înțeles așa.

Dar poți scrie aceeași interogare și pe o singură linie, nu va face nicio diferență:

var adults = from user in users where user.Age > 18 select user;

Poți, de exemplu, să ordonezi toți utilizatorii din colecție, astfel:

var orderedUsers = 
    from user in users
    select user
    orderby user.Age descending

Destul de clar și concis, nu-i așa?

Totuși, sintaxa de tip interogare are anumite limitări și nu poți transmite chiar toate instrucțiunile de care ai nevoie.

Spre exemplu, daca vrei să extragi numărul de elemente rezultate într-o interogare.

var numberOfAdults = 
 (from user in users
	where user.Age > 18
	select user).Count();

Va trebui să îmbraci întreaga interogare în paranteze și să apelezi metoda Count() , care va returna un int reprezentând numărul total de adulți.

Count() nu face parte din sintaxa de tip interogare, după cum îți poți da seama, este doar o metodă pe care o apelăm pe rezultatul interogării.

Din contra, Count() e o abordare care face parte din cealaltă categorie, a sintaxei de tip metodă.

Sintaxă de tip metodă (Method Syntax)

Sintaxa de tip metodă e ceva mai familiară, pentru că nu introduce cuvinte cheie noi, ci doar se folosește de un set de metode pentru a face aceleași operațiuni.

Hai să rescriem acum interogările de mai sus folosind sintaxa de tip metodă.

var users = new List<User>();
var adults = users.Where(user => user.Age > 18);

După cum vezi, înlocuitorul cuvântului cheie where din sintaxa de tip interogare, e chiar o metodă denumită Where, unde trebuie să pasăm o expresie lambda pentru a specifica condiția.

var orderedUsers = users.OrderByDescending(user => user.Age);

În loc de combinația orderby și descending, putem să folosim metoda OrderByDescending() în schimb.

Și probabil așa cum intuiești, pentru obținerea numărului de rezultate, putem folosi de asemenea metoda pe care am văzut-o și anterior, Count.

var adults = users
	.Where(user => user.Age > 18)
	.Count();

Poți de asemenea să folosești aceeași structura verticală pentru aranjarea condițiilor în cod și chiar îți recomand să faci asta.

Pentru că aceste expresii de LINQ pot deveni destul de complexe, iar dacă le vei scrie pe un singur rând îți va fi cu siguranță mai greu să le citești și să le înțelegi.

Concluzie

LINQ e o caracteristică extrem de potentă de care C# dispune și vitală pentru un inginer software, pentru că o mare parte din codul sistemelor software e reprezentat de accesul datelor.

LINQ facilitează comunicarea aplicațiilor .NET cu surse de date, într-o manieră extrem de performantă, nefiind nevoie ca dezvoltatorul să înțeleagă sintaxa nativă de comunicare cu sursa de date respectivă.

Dacă nu ar exista LINQ în C#, toate filtrările de date s-ar fi făcut aplicând condiții într-o buclă.

Gândește-te cât de multe bucle ai avea nevoie și cât de mult cod inutil ar trebui să scrii pentru a obține rezultatul pe care LINQ îl oferă în doar câteva apeluri de metode.

LINQ joacă un rol vital în dezvoltarea aplicațiilor cu C#, iar dacă ești programator C#, sau acum înveți să devii unul, asigură-te că stăpânești LINQ, pentru că este de asemenea și generator de foarte multe întrebări de interviu.