Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Language-Integrated Query (LINQ) è il nome di un set di tecnologie basato sull'integrazione delle funzionalità di query direttamente nel linguaggio C#. In genere, le query sui dati vengono espresse come stringhe semplici senza il controllo dei tipi in fase di compilazione o il supporto di IntelliSense. Inoltre, è necessario apprendere un linguaggio di query diverso per ogni tipo di origine dati: database SQL, documenti XML, vari servizi Web e così via. Con LINQ, una query è un costrutto di linguaggio di prima classe, proprio come classi, metodi ed eventi.
Quando si scrivono query, la parte più visibile "integrata nel linguaggio" di LINQ è l'espressione di query. Le espressioni di query vengono scritte in una sintassi di query dichiarativa. Usando la sintassi di query, si eseguono operazioni di filtro, ordinamento e raggruppamento su origini dati con un minimo di codice. Si utilizzano gli stessi modelli di espressione di query per interrogare e trasformare i dati da qualsiasi tipo di fonte di dati.
Nell'esempio seguente viene illustrata un'operazione di query completa. L'operazione completa include la creazione di un'origine dati, definire l'espressione della query e l'esecuzione della query in un'istruzione foreach
.
// Specify the data source.
int[] scores = [97, 92, 81, 60];
// Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;
// Execute the query.
foreach (var i in scoreQuery)
{
Console.Write(i + " ");
}
// Output: 97 92 81
Potrebbe essere necessario aggiungere una direttiva using
, using System.Linq;
, per compilare l'esempio precedente. Le versioni più recenti di .NET usano usi impliciti per aggiungere questa direttiva come uso globale. Le versioni precedenti richiedono di aggiungerlo nel codice sorgente.
Panoramica delle espressioni di query
- Le espressioni di query interrogano e trasformano i dati da qualsiasi origine dati abilitata per LINQ. Ad esempio, una singola query può recuperare dati da un database SQL e produrre un flusso XML come output.
- Le espressioni di query usano molti costrutti di linguaggio C# familiari, che semplificano la lettura.
- Le variabili in un'espressione di query sono tutte fortemente tipizzate.
- Una query non viene eseguita finché non si esegue l'iterazione sulla variabile di query, ad esempio in un'istruzione
foreach
. - In fase di compilazione, le espressioni di query vengono convertite in chiamate di metodo dell'operatore di query standard in base alle regole definite nella specifica C#. Qualsiasi query che può essere espressa tramite la sintassi di query può essere espressa anche tramite la sintassi del metodo. In alcuni casi, la sintassi delle query è più leggibile e concisa. In altri casi, la sintassi del metodo è più leggibile. Non esiste alcuna differenza semantica o di prestazioni tra le due forme diverse. Per altre informazioni, vedere La panoramica delle specifiche del linguaggio C# e degli operatori di query standard.
- Alcune operazioni di query, ad esempio Count o Max, non dispongono di una clausola di espressione di query equivalente e pertanto devono essere espresse come chiamata al metodo. La sintassi del metodo può essere combinata con la sintassi delle query in diversi modi.
- Le espressioni di query possono essere compilate agli alberi di espressione o ai delegati, a seconda del tipo a cui viene applicata la query. IEnumerable<T> le query vengono compilate in *delegate*. IQueryable le query e IQueryable<T> vengono compilate in alberi delle espressioni. Per altre informazioni, vedere Alberi delle espressioni.
Come abilitare le query LINQ sulla tua origine dati
Dati in memoria
Esistono due modi per abilitare l'esecuzione di query LINQ sui dati in memoria. Se i dati sono di un tipo che implementa IEnumerable<T>, eseguire una query sui dati usando LINQ to Objects. Se non ha senso abilitare l'enumerazione implementando l'interfaccia, definire i metodi dell'operatore IEnumerable<T> di query standard LINQ, in tale tipo o come metodi di estensione per tale tipo. Le implementazioni personalizzate degli operatori di query standard devono usare l'esecuzione posticipata per restituire i risultati.
Dati remoti
L'opzione migliore per abilitare l'esecuzione di query LINQ di un'origine dati remota consiste nell'implementare l'interfaccia IQueryable<T> .
Provider di LINQ IQueryable
I provider LINQ che implementano IQueryable<T> possono variare notevolmente nella loro complessità.
Un provider meno complesso IQueryable
potrebbe accedere a un singolo metodo da un servizio Web. Questo tipo di provider è molto specifico perché prevede informazioni specifiche nelle query gestite. Ha un sistema di tipi chiuso, ad esempio esponendo un singolo tipo di risultato. La maggior parte dell'esecuzione della query viene eseguita localmente, ad esempio usando le Enumerable implementazioni degli operatori di query standard. Un provider meno complesso potrebbe esaminare una sola espressione di chiamata al metodo nell'albero delle espressioni che rappresenta la query e consentire la logica rimanente della query venga gestita altrove.
Un IQueryable
provider di complessità media potrebbe avere come destinazione un'origine dati con un linguaggio di query parzialmente espressivo. Se è destinato a un servizio Web, potrebbe accedere a più metodi del servizio Web e selezionare il metodo da chiamare in base alle informazioni ricercate dalla query. Un provider di complessità media avrebbe un sistema di tipi più completo rispetto a un semplice provider, ma sarebbe comunque un sistema di tipi fisso. Ad esempio, il provider potrebbe esporre tipi con relazioni uno-a-molti che possono essere attraversate, ma non fornisce la tecnologia di mapping per i tipi definiti dall'utente.
Un provider complesso IQueryable
, ad esempio il provider Entity Framework Core , potrebbe tradurre query LINQ complete in un linguaggio di query espressivo, ad esempio SQL. Un provider complesso è più generale perché può gestire un'ampia gamma di domande nella query. Ha anche un sistema di tipi aperto e pertanto deve contenere un'infrastruttura estesa per eseguire il mapping dei tipi definiti dall'utente. Lo sviluppo di un provider complesso richiede una notevole quantità di lavoro.