Nov
19
Linq 03 - Deferred execution
Filed Under .Net, Linq | Leave a Comment
Una caratteristica importante degli operatori Linq e’ l’esecuzione differita. Cio’ consiste nel fatto che vengono eseguiti NON durante la loro costruzione ma quando vengono enumerati (cioe’ quando nell’enumeratore viene richiamato il metodo MoveNext).
Nel seguente esempio:
var nomi = new List<String>();
nomi.Add("Cristina");
IEnumerable<String> query=nomi.Select(n=>n.ToUpper());
nomi.Add("Federica");
foreach(String n in query)
Console.Write(n + "|"); Cristina|Federica|
Il nome Federica, pur essendo stato inserito dopo la creazione dell’oggetto query, e’ stato comunque preso in considerazione nel loop. Tutti gli operatori standard forniscono la deferred execution, tranne quelli che resituiscono uno scalare (First, Count) e gli operatori di conversione ToArray, ToList, ToDictionary, ToLookup, in quanto i tipi da loro restituiti non hanno meccanismi di deferred exec (ad es per Count il tipo int non puo’ essere enumerato).
La deferred exec e’ importante perche’ divide la costruzione della query dalla sua esecuzione, permettendo di costruire la query in piu’ passi, rendendo ad esempio possibili query linq to sql.
Come vengono eseguite le query?
IEnumerable<int>
source = new int[] { 5, 12, 3 },
filtered = source.Where(n => n < 10),
sorted = filtered.OrderBy(n => n),
q = sorted.Select(n => n *2);
foreach (int k in q)
Console.Write(k + “|”); // 6|10|
Si puo’ fare il paragone con una linea di produzione, che funziona solo on demand.
Costruire la query equivale a posizionare gli oggetti sulla linea mentre la linea non si muove, se non su richiesta dell’utilizzatore; a questo punto, partendo da dx verso sx, vengono attivati i rulli che fanno il loro lavoro (filtrare, ordinare, eccc)

Nov
6
Le lambda queries si basano sul concetto dei chaining operators, come nel seguente esempio:
string[] names={"Cris","Cristina","Federica"};
IEnumerable<string>query=names
.Where(n=>n.Contains("a"))
.OrderBy (n=>n.Length)
.Select (n=>n.ToUpper());
foreach(string n in names)
Console.WriteLine(n+ " | ");
//CRISTINA | FEDERICA
Sarebbe equivalente scrivere:
var filtered = names.Where (n => n.Contains (”a”));
var sorted = filtered.OrderBy (n => n.Length);
var finalQuery = sorted.Select (n => n.ToUpper( ));
Le comprehension syntax queries forniscono una modalita piu’ veloce per scrivere query linq. Una cq comincia sempre con una clausola from e termina con un select o group. La from permette di dichiarare una variabile di iterazione che looppa attraverso la input collection.
Il compilatore trasforma una cq in una query lambda, cio’ implica che cio’ che puo’ essere scritta come comprehension query puo’ anche essere scritta come query lambda (ATTENZIONE !! ma non viceversa).
IEnumerable query =
from n in names
where n.Contains ("a")
orderby n.Length
select n.ToUpper( );
viene trasformata in:
IEnumerable query = names
.Where (n => n.Contains ("a"))
.OrderBy (n => n.Length)
.Select (n => n.ToUpper( ));
Sebbene superficialmente ricordino l’SQL, ci sono delle differenze: la query Linq si basa su espressioni C# e ne segue le regole, ad esempio non si puo’ usare una variabile prima di averla dichiarata, mentre in SQL si possono usare alias nella select che verranno definiti successivamente nella clausola from.
Una subquery linq e’ una espressione c# che non richiede sintassi speciale, le subquery sql talvolta richiedono regole particolari.
Con linq i dati passano sequenzialmente da sx a dx (o da su a giu a seconda di come lo si guarda), con l’sql l’ordine e’ piu’ casuale.
Una query linq e’ costituita da una pipeline di operatori che accettano e restituiscono sequence, l’sql comprendere una rete di clausole che lavorano su insiemi non ordinati.
Detto questo, la sintassi e’ simile.
A questo punto la domanda nasce spontanea? Lambda o comprehension query?
Ognuna ha i suoi vantaggi.
Le cq hanno una sintassi piu’ semplice nei seguenti casi:
- clausola let per usare una nuova variabile durante una iterazione
- utilizzo degli operatori SelectMany, Join, GroupJoin
Per gli operatori Where,OrderBy e Select l’uso e’ a discrezione dello sviluppatore.
Per tutti gli operatori che non sono Where, Select, SelectMany OrderBy, ThenBy, OrderByDescending, ThenByDescending Group, Join, GroupJoin si e’ obbligati a usare le lambda perche’ non esiste l’equivalente in CQ.
Mixed query
La perversione puo’ portare anche a utilizzarle entrambe, a patto che ogni componente cq sia completo, cioe’ inizio from from e termino con select o group.
Ad esempio:
int count = (from name in names
where n.Contains (”a”)
select name ).Count( );
Nov
6
Il Linq - Language Integrated Query - e’ stato inserito a partire dalla versione 3.5 del .Net Framework e consente di effettuare query strutturate su collezioni locali di oggetti che implementano l’interfaccia IEnumerable<>, tra cui arrays, XML Dom e su data sources remote (ad esempio tabelle Sql).
Le unita basilari di dati sono le sequence (oggetto che implementa IEnumerable) e gli elements (ogni singolo oggetto facente parte della sequence), come nel seguente esempio la sequence names comprende 3 elementi:
string[] names = { “Cris”, “Cristina”, “Federica” };
Una query Linq e’ un’espressione che trasforma una sequenza utilizzando utilizzando degli operatori:
IEnumerable<string> filteredNames =
System.Linq.Enumerable.Where(
names, n => n.Length > 4);
In questo caso l’operatore Where filtra in modo da estrarre solo gli elementi di lunghezza superiore a 4.
Dato che gli operatori sono implementati come metodi, si puo’ anche scrivere:
IEnumerable<string> filteredNames =
names.Where(n => n.Length > 4);
I due esempi precedenti utilizzano la lambda syntax, quello che segue la comprehension syntax:
IEnumerable<string> filteredNames=
from n in names
where n.Length>4
select n;
In tutti i suddetti casi, il risultato:
foreach (string n in filteredNames)
Console.Write(n + ” | “);
Produce: Cristina | Federica |