0% found this document useful (0 votes)
162 views

LINQ - Language Integrated Query Cereri Asupra Datelor

LINQ (Language Integrated Query) is a Microsoft technology that provides a language-level mechanism for executing queries over various data sources. Some examples of data sources include in-memory arrays and collections, databases, XML documents, etc. LINQ allows operations like conversions, sorting, filtering a set, etc. to be performed via query syntax. Key components of LINQ include LINQ to Objects for in-memory collections, LINQ to XML for XML documents, and LINQ to SQL for querying SQL databases. Expression trees represent query operations as expression trees for deferred execution and translation to other languages like SQL.

Uploaded by

xact33
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
162 views

LINQ - Language Integrated Query Cereri Asupra Datelor

LINQ (Language Integrated Query) is a Microsoft technology that provides a language-level mechanism for executing queries over various data sources. Some examples of data sources include in-memory arrays and collections, databases, XML documents, etc. LINQ allows operations like conversions, sorting, filtering a set, etc. to be performed via query syntax. Key components of LINQ include LINQ to Objects for in-memory collections, LINQ to XML for XML documents, and LINQ to SQL for querying SQL databases. Expression trees represent query operations as expression trees for deferred execution and translation to other languages like SQL.

Uploaded by

xact33
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

LINQ - Language Integrated Query LINQ - Language Integrated Query = Cereri asupra datelor

12.12.2012

LINQ este o tehnologie Microsoft ce furnizeaza un mecanism la nivel de limbaj pentru a executa cereri de date de orice tip. Cateva exemple :
Ex 1

using System; using System.Linq; string[] greetings = {"hello world", "hello LINQ", "hello Apress"}; var items = from s in greetings where s.EndsWith("LINQ") select s; foreach (var item in items) Console.WriteLine(item); Ex. 2 using System; using System.Linq; using System.Xml.Linq; XElement books = XElement.Parse( @"<books> <book> <title>Pro LINQ: Language Integrated Query in C# 2008</title> <author>Joe Rattz</author> </book> <book> <title>Pro WF: Windows Workflow in .NET 3.0</title> <author>Bruce Bukovics</author> </book> <book> <title>Pro C# 2005 and the .NET 2.0 Platform, Third Edition</title> <author>Andrew Troelsen</author> </book> </books>"); var titles = from book in books.Elements("book") where (string) book.Element("author") == "Joe Rattz" select book.Element("title"); foreach(var title in titles) Console.WriteLine(title.Value);

Ioan Asiminoaei

LINQ - Language Integrated Query


Ex. 3 string[] numbers = { "0042", "010", "9", "27" }; int[] nums = numbers.Select(s => Int32.Parse(s)).ToArray(); foreach(int num in nums) Console.WriteLine(num);

12.12.2012

Ex. 4
public class Employee { public int id; public string firstName; public string lastName; public static ArrayList GetEmployees() { ArrayList al = new ArrayList(); al.Add(new Employee { id = 1, firstName = "Joe", lastName = "Rattz"} ); al.Add(new Employee { id = 2, firstName = "William", lastName = "Gates"} ); al.Add(new Employee { id = 3, firstName = "Anders", lastName = "Hejlsberg"} ); return(al); } } public class Contact { public int Id; public string Name; public static void PublishContacts(Contact[] contacts) { foreach(Contact c in contacts) Console.WriteLine("Contact Id: {0} Contact: {1}", c.Id, c.Name); } }

...
ArrayList alEmployees = Employee.GetEmployees(); Contact[] contacts = alEmployees.Cast<Employee>() .Select(e => new Contact { Id = e.id, Name = string.Format("{0} {1}", e.firstName, e.lastName) }).ToArray<Contact>(); PublishContacts(contacts);

Rezultatul este:
Contact Id: 1 Contact: Joe Rattz Contact Id: 2 Contact: William Gates
Ioan Asiminoaei

LINQ - Language Integrated Query


Contact Id: 3 Contact: Anders Hejlsberg

12.12.2012

LINQ LINQ este o tehnologie Microsoft ce furnizeaza un mecanism la nivel de limbaj pentru a executa cereri de date de orice tip. Aceste tipuri includ tablouri si colectii in memorie, baze de date, documente XML, etc. Printre altele LINQ poate face conversii, poate sorta, poate obtine o submultime a unei multimi date, etc.
// conversie array de string-uri in array de int. Aceasta este o cerere. string[] numbers = { "0042", "010", "9", "27" }; int[] nums = numbers.Select(s => Int32.Parse(s)).ToArray(); // se face si sortarea int[] nums = numbers.Select(s => Int32.Parse(s)).OrderBy(s => s).ToArray();

In LINQ, multimea de obiecte returnata se numeste sir. Majoritatea sirurilor din LINQ sunt de tip IEnumerable<T> sau dintr-un tip derivat din IEnumerable<T> , unde T este tipul de data al obiectelor memorate in sir (int, string, double, etc.). La runtime cand se cer elemente din colectie, are loc un proces de construire a elementelor submultimii. In acest moment pot aparea exceptii. Ex.
string[] strings = { "Iasi", "Pascani", null, "Harlau" }; Console.WriteLine("Inainte ca Where() sa fie apelat."); // definim multimea ieStrings IEnumerable<string> ieStrings = strings.Where(s => s.Length == 3); Console.WriteLine("Duap ce Where() este apelat."); // Cand se va executa foreach va aparea o exceptie pentru ca // al 3-lea element al sirului are valoarea null, vedeti Where... // Daca nu se extragem elemente din ieStrings nu va aparea exceptia foreach(string s in ieStrings) { Console.WriteLine("Procesat " + s); }

Componente : 1. LINQ to Objects este numele dat API-ului IEnumerable<T> pentru operatorii de cereri standard. Putem face cereri asupra tablourilor sau colectiilor din memorie. Operatorii standard sunt metode statice ale clasei System.Linq.Enumerable. 2. LINQ to XML API dedicat sa lucreze cu XML. Trebuie sa adaugam o referinta la proiect System.Xml.Linq.dll si apoi using System.Xml.Linq; 3. LINQ to DataSet API Linq pentru DataSet-uri.

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

4. LINQ to SQL API IQuerable<T> ce permite Linq sa lucreze cu SQL Server. Trebuie referinta la System.Data.Linq.dll si apoi using System.data.Linq ; 5. LINQ to Entities alternativa la Linq folosit pentru interfata cu bazele de date. Se decupleaza entitatea model obiect de baza de date (fizic) prin crearea unei logici intre cele doua niveluri.

Trasaturi noi in .NET


Expresii lambda (Lambda expressions) ; Arbori de expresii (Expression trees); Cuvantul cheie var, obiecte si initializarea colectiilor, tipuri anonime, new forma noua; Metode extinse (Extension methods); Metode partiale (Partial methods); Expresii cerere (Query expressions).

Metode partiale
Scriem prototipul intr-un loc si codul in alt loc. Daca nu scriem codul atunci compilatorul nu emite cod pentru acea metoda, iar apelul metodei nu are efect (nici o exceptie). Putem sa le folosim cand dezvoltam un tip si nu implementam toate metodele. Le vom implementa mai tarziu sau altcineva va implementa acele metode dar nu va avea acces la implementarea metodelor facuta de noi. Reguli pentru metodele partiale Metodele partiale trebuiesc sa fie definite si implementate numai in clase partiale. Metodele partiale trebuie sa specifice modificatorul partial. Metodele partiale sunt private dar nu trebuie sa specifice modificatorul private, in caz contrar eroare la compilare. Metodele partiale trebuie sa returneze void. Metodele partiale pot fi neimplementate. Metodele partiale pot fi statice. Metodele partiale pot avea argumente. Ex.
namespace PM { partial class A { partial void MetodaPartiala(string s); } // Ceea ce urmeaza trebuie sa fie in alt fisier partial class A { // Daca comentam aceasta linie programul tot se va compila partial void MetodaPartiala(String s) { Console.WriteLine("MetodaPartiala apelata cu: {0}", s); } }
Ioan Asiminoaei

LINQ - Language Integrated Query


} Ex. public partial class PartialA { partial void Start(int count); partial void End(int count); public PartialA() { int count = 0; Start(++count); Console.WriteLine("In ctor PartialA."); End(++count); Console.WriteLine("count = " + count); } }

12.12.2012

Obs. count ramane nemodificat (Verificati!). Metodele partiale Start si End nu sunt implementate.

Metode extinse
O metoda extinsa este o metoda statica a unei clase statice pe care o putem apela ca si cum ar fi o metoda de instanta a unei alte clase. Sunt de folos cand dorim sa extindem o clasa ce e declarata sealed sau nu avem codul clasei.

Declararea primului parametru al unei metode cu cuvantul cheie this face ca metoda sa fie extinsa. Metoda trebuie sa fie statica, iar clasa in care se declara trebuie sa fie statica.
Se extinde clasa data de primul parametru al metodei (in exemplul de mai jos String). Ex.
public static class StringConversions { public static double ToDouble(this string s) { return Double.Parse(s); } public static bool ToBool(this string s) { return Boolean.Parse(s); } }

...
// Se apeleaza ca in exemplul de mai jos string str = 123.45; Console.WriteLine(str.ToDouble()); Observatie

Metodele de instanta ale obiectului au prioritate fata de metodele extinse.

Ioan Asiminoaei

LINQ - Language Integrated Query Lambda expresii


Scopul lor este de a furniza un algoritm ca argument al unei metode. Delegates anonimi. Vezi .NET 2.0 si ca exemplu clasa Ex4 pentru acest curs. In C# lambda expresia arata astfel :
(param1, param2, paramN) => { statement1; statement2; statementP; return(lambda_expression_return_type); }

12.12.2012

Se citeste astfel: pentru valorile de intrare date prin parametrii param1, param2, ..., paramN se va executa codul statement1 ; statement2 ;...statementP iar valoarea returnata este cea data de return (aici se stabileste si tipul valorii returnate). In Ex4 tipul valorii de retur (ce este bool) este stabilita de delagate-ul definit in clasa DelegateAnonim :
public delegate bool IntFilter(int i);

Exemple:
x=> x.Length x => Procesat + x x => x.Length > 0 (x, y) => x == y // // // // tip tip tip tip returnat returnat returnat returnat int string (x trebuie sa fie string) bool bool

Observatie: Lambda expresia trebuie sa accepte in intrare tipurile specificate de delegate si sa returneze acelasi tip definit de delegate. Algoritmii complecsi sau reutilizati ar trebui implementati in cadrul metodelor cu nume si nu in cadrul delegates anonimi sau lambda expresii.

Ioan Asiminoaei

LINQ - Language Integrated Query Expression Trees

12.12.2012

Eexpression trees : data este reprezentata sub forma de arbore ca rezultat al unui operator de cereri,
operator dat sub forma unei expresii lamba. Evaluarea se face simultan si nu secvential. Ex. (nu e sub forma unei cereri expression trees) forma C#
int[] nums = new int[] { 6, 2, 7, 1, 9, 3 }; IEnumerable<int> set4 = nums .Where(i => i < 4) .OrderBy(i => i);

Se executa mai intai Where si apoi OrderBy (secvential). Ce emite compilatorul ? Daca operatorul (Where in cazul nostru) este declarat sa accepte un delegate, atunci se emite cod IL. Daca operatorul este declarat sa accepte o expresie a unei metode delegate, se emite o expresie tree. Sa vedem cum este definit operatorul Where. Este in clasa System.Linq.Enumerable (Linq to Objects):
public static IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, bool> predicate);

O alta implementare este in Linq to SQL in clasa System.Linq.Queryable:


public static IQueryable<T> Where<T>( this IQueryable<T> source, System.Linq.Expressions.Expression<Func<int, bool>> predicate);

Prima forma produce cod IL, iar a doua forma produce expression tree.

var
Cuvantul cheie var permite ca tipul de data al unui obiect sa fie acelasi cu tipul obiectului folosit la initializare.
var mv = new { Nume = Ionescu , Prenume = Ion } ; var anonim = new {Nume = Ionescu, Inaltime = 1.85, Varsta = 20};
// string, float, int

Console.WriteLine(anonim.Nume);

Trebuie initializat in momentul crearii. In exemplul de mai sus am definit un tip anonim ce contine doua date membru: Nume si Prenume. Acest tip de data nu are nici un nume.

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

Tipurile anonime sunt foarte des utilizate in operatorii Select sau SelectMany. Daca nu ar exista aceste tipuri ar trebui sa construim cate o clasa pentru fiecare expresie pe care dorim sa o folosim. Vezi ex cu clasa TipAnonim.

Query Expressions expresii pentru creare cereri


Query expressions permit cererilor LINQ sa fie scrise intr-o forma asemanatoare cu cea data de SQL. Cerere scrisa in sintaxa .NET:
string[] names = { "Adams", "Arthur", "Buchanan", "Bush", "Carter", "Cleveland", "Clinton", "Coolidge", "Eisenhower", "Fillmore", "Ford", "Garfield", "Grant", "Harding", "Harrison", "Hayes", "Hoover", "Jackson", "Jefferson", "Johnson", "Kennedy", "Lincoln", "Madison", "McKinley", "Monroe", "Nixon", "Pierce", "Polk", "Reagan", "Roosevelt", "Taft", "Taylor", "Truman", "Tyler", "Van Buren", "Washington", "Wilson"}; IEnumerable<string> sequence = names .Where(n => n.Length < 6) .Select(n => n); foreach (string name in sequence) { Console.WriteLine("{0}", name); }

iar echivalentul folosind query expressions este:


IEnumerable<string> sequence = from n in names where n.Length < 6 select n;

Ioan Asiminoaei

LINQ - Language Integrated Query


Reguli pentru expresii :

12.12.2012

1. O expresie trebuie sa inceapa cu clauza from. 2. Ceea ce urmeaza poate sa contina zero sau mai multe clauze from, let sau where. O clauza from este un generator ce declara una sau mai multe variabile enumerator ce enumereaza peste un sir sau un join de mai multe siruri. 3. In continuare se poate folosi clauza orderby. 4. Restul expresiei poate fi urmat de clauza select sau group iar in final optional clauza into sau zero sau mai multe clauze join sau din nou 2. Pentru mai multe detalii consultati documentatia din MSDN privitaore la LINQ.
query-expression: from-clause query-body from-clause: from typeopt identifier in expression join-clausesopt join-clauses: join-clause join-clauses join-clause join-clause: join typeopt identifier in expression on expression equals expression join typeopt identifier in expression on expression equals expression into identifier query-body: from-let-where-clausesopt orderby-clauseopt select-or-group-clause query-continuationopt from-let-where-clauses: from-let-where-clause from-let-where-clauses from-let-where-clause from-let-where-clause: from-clause let-clause where-clause let-clause: let identifier = expression where-clause: where boolean-expression orderby-clause: orderby orderings orderings: ordering orderings , ordering ordering: expression ordering-directionopt ordering-direction: ascending
Ioan Asiminoaei

LINQ - Language Integrated Query


descending select-or-group-clause: select-clause group-clause select-clause: select expression group-clause: group expression by expression query-continuation: into identifier join-clausesopt query-body

12.12.2012

Linq to Objects IEnumerable<T>, secvente si operatorii de cereri standard


IEnumerable<T>, este o interfata pe care o implementeaza toate colectiile generice din C# 2.0.

Aceasta interfata permite enumerarea elementelor colectie. Vezi Colectii generice de pe pagina http://www.infoiasi.ro/~iasimin. O secventa este un termen logic pentru o colectie ce implementeaza interfata IEnumerable<T>. Daca avem o variabila de tipul IEnumerable<T>, atunci putem spune ca avem un sir (o secventa) de elemente de tipul T. Majoritatea operatorilor standard de cereri ( Standard Query Operators ) sunt metode extinse pe clasa statica System.Linq.Enumerable si au ca prim argument IEnumerable<T>. Din cauza ca sunt metode extinse, este de preferat sa le apelam pe variabile de tipul IEnumerable<T> in loc de a le pasa in metoda ca primul argument. Operatorii Cast<T>() si OfType<T>() folositi pentru a face conversia colectiilor la
IEnumerable<T>.

Se folosesc pentru colectii ce nu implementeaza IEnumerable<T>.


Cast incearca sa faca conversia tuturor elementelor existente si daca exista un element pe care esueaza

va arunca o exceptie. OfType va pune numai acele elemente pentru care conversia reuseste.

Ioan Asiminoaei

LINQ - Language Integrated Query Returning IEnumerable<T>, Yielding, and Deferred Queries

12.12.2012

Din cauza ca aceste tipuri de cereri ce returneaza IEnumerable<T> definesc numai prototipul cererii, putem scrie codul ce defineste cererea o singura data si folosim aceasta cerere de mai multe ori in enumerarea elementelor.
// Creaza un tablou de int. int[] intArray = new int[] { 1,2,3 }; IEnumerable<int> ints = intArray.Select(i => i); // Afiseaza rezultatele. foreach(int i in ints) Console.WriteLine(i); // Schimba un element in sursa de date. intArray[0] = 5; Console.WriteLine("---------"); // Afiseaza rezultatele din nou. foreach(int i in ints) Console.WriteLine(i);

Am creat cererea o singura data si o apelam de mai multe ori. Daca nu ar fi asa, rezultatul enumerarii ar fi fost identic in cele doua cazuri. Daca vrem ca cererea sa nu fie amanata la executie putem folosi unul din operatorii de conversie ce nu returneaza un IEnumerable<T>. Acestia sunt : ToArray, ToList, ToDictionary sau ToLookup. Exemplu:
// Creaza un tablou de int. int[] intArray = new int[] { 1, 2, 3 }; List<int> ints = intArray.Select(i => i).ToList(); // Afiseaza rezultatele. foreach(int i in ints) Console.WriteLine(i); // Schimba un element in sursa de date. // Modificarea nu este vazuta pentru ca cererea nu este reimprospatata (deferred) intArray[0] = 5; Console.WriteLine("---------"); // Afiseaza rezultatele din nou. foreach(int i in ints) Console.WriteLine(i);

Delegates de tip Func

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

Multi dintre operatorii standard de cereri au in prototipul lor un argument de tip delegate, numit Func. Acest lucru ne scuteste de a declara in mod explicit un tip delegate.
public public public public public delegate delegate delegate delegate delegate TR TR TR TR TR Func<TR>(); Func<T0, TR>(T0 a0); Func<T0, T1, TR>(T0 a0, T1 a1); Func<T0, T1, T2, TR>(T0 a0, T1 a1, T2 a2); Func<T0, T1, T2, T3, TR>(T0 a0, T1 a1, T2 a2, T3 a3);

TR se refera la tipul de data returnat.

Exemplu Prototipul pentru operatorul Where este (exista doua prototipuri):


public static IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, bool> predicate);

Observam ca este metoda extinsa pentru IEnumerable<T>. Argumentul predicat este specificat ca Func<T, bool>. De aici observam ca metoda predicate sau lambda expresia accepta un singur argument, parametrul T si returneaza un bool. Tipul returnat este ultimul in lista de parametri. Ex
// Cream un array de int int[] ints = new int[] { 1,2,3,4,5,6 }; // Declaram delegate Func<int, bool> MaiMareCaDoi = i => i > 2; // Declaram codul pentru cerere ... va fi deferred IEnumerable<int> result = ints.Where(MaiMareCaDoi); // Afisare rezultat foreach(int i in result) Console.WriteLine(i); Rezultat: 3, 4, 5, 6

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

Table 3-1. Standard Query Operators Alphabetical Cross-Reference

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

Namespace-urile necesare sunt:


using using using using System.Linq; System.Collections; System.Collections.Generic; System.Data.Linq;

Operatori de restrictii
Where : filtreaza elementele dintr-un sir. public static IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, bool> predicate); public static IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, int, bool> predicate); source contine sirul de elemente; predicate metoda delegate folosita pentru filtrare. int reprezinta indexul elementului din sirul de intrare - source (zero based). Out: obiecte pentru care predicate a returnat true. Exceptii: ArgumentNullException daca exista un argument null.

In:

Ex
string[] orase = {Iasi, Vaslui, Botosani, Cluj, Timisoara, Bacau}; // orasele ce incep cu litera I IEnumerable<string> sir = orase.Where(o => o.StartsWith(I)); foreach(string s in sir) Console.WriteLine(s);

Ioan Asiminoaei

LINQ - Language Integrated Query


IEnumerable<string> sirimpar = orase.Where((o,i) => (i &1) == 1); foreach(string s in sirimpar) Console.WriteLine(s);

12.12.2012

Ex:
IEnumerable<Carti> x = carti.Where(p => p.Pret >= 10);

In C# 3.0 query expression arata astfel:


IEnumerable<Carti> x = from p in carti where p.Pret >= 10 select p;

carti reprezinta colectia de Carti (vezi exemplul de cod).


(SQL: Select * From carti p Where p.Pret >= 10).

Proiectie
Operatorii de proiectie returneaza un sir de elemente ce sunt generate prin selectarea elementelor sau instantierea impreuna a noi elemente ce contin portiuni ale elementelor din sirul de intrare. Tipul de data al elementelor din sirul de iesire poate fi diferit de tipul de data al elementelor din sirul de intrare. Select folosit pentru a crea un sir de iesire de un anumit tip folosind in intrare un sir de un alt tip.
public static IEnumerable<S> Select<T, S>( this IEnumerable<T> source, Func<T, S> selector); public static IEnumerable<S> Select<T, S>( this IEnumerable<T> source, Func<T, int, S> selector);

In intrare avem tipul T, in iesire avem tipul S. Metoda delegate selector este folosita pentru a face selectia. Exceptii: ArgumentNullException daca exista un argument null. Ex :
IEnumerable<int> nrcar = orase.Select(o => o.Length) ; foreach(int i in nrcar) Console.WriteLine({0}, i); var items = orase.Select((o, i) => new { oras = o, nc = o.Length} ); foreach(var v in items) Console.WriteLine( Oras : {0} are {1} caractere in nume, v.oras,v.nc);

SelectMany creaza o proiectie de 1-n. Returneaza zero sau mai multe elemente pentru fiecare element din intrare.

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

public static IEnumerable<S> SelectMany<T, S>( this IEnumerable<T> source, Func<T, IEnumerable<S>> selector); public static IEnumerable<S> SelectMany<T, S>( this IEnumerable<T> source, Func<T, int, IEnumerable<S>> selector);

In intrare un element de tip T, in iesire un element de tip S, iar delegate este dat de selector. Pentru fiecare element din sirul de intrare va rezulta un element concatenat in iesire. Exceptii: ArgumentNullException daca exista un argument null.
IEnumerable<char> chars = orase.SelectMany(o => o.ToArray()); foreach (char ch in chars) Console.WriteLine(ch);

Folosind clasele Scriitori si Carti putem crea urmatoarea colectie :


// Colectiile de mai jos au in comun o data membru id Scriitori[] scriitori = Scriitori.GetScriitori(); Carti[] carti = Carti.GetCarti(); var items = scriitori .OrderBy(s => s.Nume) .SelectMany(e => carti .Where(eo => eo.id == e.id) .Select(eo => new { id = eo.id, Nume = e.Nume, Prenume = e.Prenume, titlu = eo.Titlu } )); foreach (var item in items) Console.WriteLine(item);
(SQL: Select eo.id, e.Nume, e.Prenume, eo.Titlu From carti eo, scriitori e Where eo.id = e.id Order by e.Nume)

Ioan Asiminoaei

LINQ - Language Integrated Query

12.12.2012

Partitionare acesti operatori ne permit sa returnam un sir ce este o submultime a sirului de intrare.
Take returneaza un numar specificat de elemente din sirul de intrare plecand de la inceputul sirului. public static IEnumerable<T> Take<T>( this IEnumerable<T> source, int count);

In : count specifica cate elemente trebuie sa luam din sirul de intrare, incepand cu primul element. Ex :
IEnumerable<string> items = orase.Take(5); TakeWhile returneaza elemente din sirul de intrare atata timp cat conditia este adevarata. public static IEnumerable<T> TakeWhile<T>( this IEnumerable<T> source, Func<T, bool> predicate); public static IEnumerable<T> TakeWhile<T>( this IEnumerable<T> source, Func<T, int, bool> predicate); Exceptii: ArgumentNullException

Skip se vor sari atatea elemnete din sirul de intrare cate sunt specificate in count.
public static IEnumerable<T> Skip<T>( this IEnumerable<T> source, int count); Exceptii: ArgumentNullException

SkipWhile se vor sari elementele din intrare pana cand conditia devine false.
public static IEnumerable<T> SkipWhile<T>( this IEnumerable<T> source, Func<T, bool> predicate); public static IEnumerable<T> SkipWhile<T>( this IEnumerable<T> source, Func<T, int, bool> predicate); Exceptii: ArgumentNullException Concatenare acesti operatori permit concatenarea sirurilor de acelasi tip. Concat concateneaza doua siruri de intrare si rezulta un singur sir. public static IEnumerable<T> Concat<T>( this IEnumerable<T> first, IEnumerable<T> second);

Ioan Asiminoaei

LINQ - Language Integrated Query


Ex: IEnumerable<string> items = orase.Take(2).Concat(orase.Skip(1));

12.12.2012

Ordonarea Operatorii OrderBy si OrderByDescending au ca parametru de intrare un sir de tip IEnumerable<T> si returneaza un sir de tip IOrderedEnumerable<T>. Deci nu putem folosi in intrare o iesire de la OrderBy sau OrderByDescending. Daca dorim ordonari dupa mai multe campuri vom folosi ThenBy si/sau ThenByDescending, operatori ce permit ca sirul de intrare sa fie de tip IOrderedEnumerable<T>.
Ex. eronat: inputSequence.OrderBy(s => s.LastName).OrderBy(s => s.FirstName) Ex. corect inputSequence.OrderBy(s => s.LastName).ThenBy(s => s.FirstName) OrderBy / OrderByDescending (acelasi prototip) public static IOrderedEnumerable<T> OrderBy<T, K>( this IEnumerable<T> source, Func<T, K> keySelector)

unde (deci K trebuie sa fie un tip ce suporta o relatie de ordine): K : IComparable<K>;


public static IOrderedEnumerable<T> OrderBy<T, K>( this IEnumerable<T> source, Func<T, K> keySelector, IComparer<K> comparer);

Pentru prototipul 2 nu este necesar ca tipul K sa implementeze interfata IComparable. Se foloseste delegate comparer. In acest caz putem furniza metoda noastra ce va face compararea. Interfata IComparer este definita astfel:
interface IComparer<T> { int Compare(T x, T y); }

deci noi va trebui sa scriem cod pentru metoda Compare.


ThenBy / ThenByDescending aceleasi observatii ca la OrderBy public static IOrderedEnumerable<T> ThenBy<T, K>( this IOrderedEnumerable<T> source, Func<T, K> keySelector) unde:

Ioan Asiminoaei

LINQ - Language Integrated Query


K : IComparable<K>; public static IOrderedEnumerable<T> ThenBy<T, K>( this IOrderedEnumerable<T> source, Func<T, K> keySelector, IComparer<K> comparer); Ex:

12.12.2012

IEnumerable<string> items = orase.OrderBy(s => s.Length).ThenBy(s => s); Reverse returneaza acelasi sir dar in ordine inversa. public static IEnumerable<T> Reverse<T>( this IEnumerable<T> source); Join

- join pe mai multe siruri.


public static IEnumerable<V> Join<T, U, K, V>( this IEnumerable<T> outer, IEnumerable<U> inner, Func<T, K> outerKeySelector, Func<U, K> innerKeySelector, Func<T, U, V> resultSelector);

Operatorul Join va returna un obiect care in timpul enumerarii va enumera mai intai elementele din sirul inner de tip U, apeland metoda innerKeySelector odata pentru fiecare element si memoreaza elementul, referit de cheia sa, intr-o tabela hash. In continuare, obiectul returnat va enumera sirul outer de elemente de tip T pe care se va apela metoda outerKeySelector pentru a obtine cheia si a regasi elementele din sirul inner ce se potrivesc. Obiectul returnat va apela metoda resultSelector ce primeste atat elementele din outer cat si cele din inner. Aceasta metoda returneaza un tip V. Exceptii: ArgumentNullException.
Scriitori[] scriitori = Scriitori.GetScriitori(); Carti[] carti = Carti.GetCarti(); Console.WriteLine("\nPrintJoin ... "); var items = scriitori .Join( carti, // inner sequence e => e.id, // outerKeySelector o => o.id, // innerKeySelector (e, o) => new // resultSelector { id = e.id, nume = string.Format("{0} {1}", e.Nume, e.Prenume), pret = o.Pret }); foreach (var item in items) Console.WriteLine(item);

Ioan Asiminoaei

LINQ - Language Integrated Query


GroupJoin

12.12.2012

Operatorul GroupJoin efectueaza o grupare a doua siruri, grupare bazata pe o cheie definita in cadrul elementelor sirului.
public static IEnumerable<V> GroupJoin<T, U, K, V>( this IEnumerable<T> outer, IEnumerable<U> inner, Func<T, K> outerKeySelector, Func<U, K> innerKeySelector, Func<T, IEnumerable<U>, V> resultSelector);

Argumentele outerKeySelector si innerKeySelector specifica functiile ce extrag valorile cheii dupa care se face join, din sirul outer respectiv inner. Argumentul resultSelector specifica o functie ce creaza un element al rezultatului folosind elemente din inner si outer. Cand este enumerat obiectul returnat de GroupJoin, mai intai se enumera elementele din sirul inner si se evalueaza functia innerSelector odata pentru fiecare element, colectand elementele intr-o tabela hash. Dupa ce au fost colectate elementele in tabela hash, sirul outer este enumerat. Pentru fiecare element din acest sir se evalueaza functia outerSelector, iar cheia ce rezulta se cauta in tabela hash a elementelor din inner si apoi este evaluata functia resultSelector ce va furniza elementul sau daca nu exista potrivire nu se returneaza nimic.. Nu exista echivalent in SQL pentru aceasta functie.

Ioan Asiminoaei

You might also like