LINQ (Language-Integrated Query) rappresenta un set di funzionalità introdotto in Visual Studio 2008 che migliora la gestione delle query nella sintassi dei linguaggi C# e Visual Basic.
Select
La variabile di query numQuery non esegue mai una query, questa viene effettivamente eseguita solo quando la query viene chiamata. Tale variabile è di tipo IEnumerable<T>, quindi facilmente ciclabile con un foreach.
Funzioni di aggregazione
Alla variabile di query posso applicare funzioni di aggregazione, come Count, Max, Average e First. Queste istruzioni eseguono la query e restituiscono un solo valore, non un IEnumerable.
Esecuzione immediata
Se voglio eseguire immediatamente una query e salvare i risultati in cache conviene utilizzare il metodo ToArray();.
Esempi
Creazione della sorgente dei dati
Creiamo la sorgente dei dati:
Studenti il cui punteggio nel primo test era superiore a 90
Si noti che, poiché viene selezionato l’intero oggetto Student (select student
) il tipo della query è quindi IEnumerable<Student>
.
Se io facessi invece select student.Last
(che è una stringa), il tipo della query sarebbe IEnumerable<string>
.
Per eseguire la query è necessario scrivere il ciclo foreach
Ordinamento dei risultati
Sarà più semplice analizzare i risultati se vengono ordinati. È possibile ordinare la sequenza restituita in base a qualsiasi campo accessibile negli elementi di origine. Ad esempio, la clausola orderby riportata di seguito ordina i risultati alfabeticamente dalla A alla Z in base al cognome di ogni studente. Aggiungere alla query la clausola orderby, subito dopo l’istruzione where e prima dell’istruzione select:
Raggruppamento dei risultati
Il raggruppamento è una funzionalità potente nelle espressioni di query. Una query con una clausola group genera una sequenza di gruppi e ogni gruppo contiene un oggetto Key e una sequenza costituita da tutti i membri di tale gruppo. Nella nuova query riportata di seguito gli studenti vengono raggruppati utilizzando la prima lettera del cognome come chiave.
Il tipo della query è stato ora modificato. Vengono ora generate una sequenza di gruppi con il tipo char come chiave e una sequenza di oggetti Student. Poiché il tipo della query è stato modificato, nel codice seguente viene modificato anche il ciclo di esecuzione foreach:
Utilizzare le variabili in modo implicito
Codificare in modo esplicito IEnumerables di IGroupings può risultare noioso. È possibile scrivere la stessa query e il ciclo foreach in modo notevolmente più pratico utilizzando var. La parola chiave var non modifica i tipi degli oggetti ma indica solo al compilatore di dedurre i tipi.
Ordinare i gruppi in base al valore della chiave
Quando si esegue la query precedente, i gruppi non sono in ordine alfabetico. Per modificare questo comportamento, è necessario fornire la clausola orderby dopo la clausola group. Per utilizzare la clausola orderby, è necessario però utilizzare prima un identificatore che funga da riferimento ai gruppi creati dalla clausola group. Fornire l’identificatore utilizzando la parola chiave into, come segue:
È possibile utilizzare la parola chiave let per introdurre un identificatore per qualsiasi risultato dell’espressione di query. Questo identificatore può risultare utile come nell’esempio seguente o può migliorare le prestazioni archiviando i risultati di un’espressione in modo da non doverla calcolare più volte.
Gestione dei valori di ritorno delle SP
FirstOrDefault()
Restituisce il primo elemento di una sequenza o un valore predefinito se la sequenza non contiene elementi. Da usare (quasi sempre) quando ho un solo record di ritorno da una SP.
Single()
Restituisce il singolo elemento di una sequenza e genera un’eccezione se nella sequenza non è presente esattamente un elemento.
SingleOrDefault()
Restituisce il singolo elemento di una sequenza o un valore predefinito se la sequenza è vuota; questo metodo genera un’eccezione se esiste più di un elemento nella sequenza.
toList()
Crea un oggetto List<T> da un oggetto IEnumerable<T>. Da usare quando una SP restituisce più di un record.
Lamda syntax
Come parametro in ingresso alle funzioni linq (principalemente firstOrDefault()) posso scrivere delle lamda espressioni. Assumendo di avere il seguente array:
La seguente espressione
indica:
- FirstOrDefault(): voglio solo un elemento
name => name.EndsWith ("y")
l’elemento che voglio deve terminare per “y”. è la stessa cosa della sintassi di rubyarray.map{|a| a.ends_with("y")}
. Invece di “name” posso scrivere anche “n” o quello che voglio, serve come riferimento per l’esecuzione della lamda espressione.
Il risultato sarà infatti:
Allo stesso modo se cambio l’espressione in:
Ottengo:
Esempi
Ho la seguente SP che mi ritorna un elenco di AidMotivoReclamo
(funzione ToList()
)
Controllare se esiste un record con un determinato campo valorizzato
Voglio vedere se esiste almeno un aidReclami
che abbia il campo XMLConfig_Aid
con un valore non nullo
Selezionare il primo record che ha un determinato campo valorizzato
Allo stesso modo di prima ho:
Ciclare tutti i valori che hanno una determinata caratteristica
Ticket.Fields
con UtilityItem
formato da string Codice
e string Descrizione