Condividi tramite


Scrittura della prima query LINQ (Visual Basic)

Una query è un'espressione che recupera dati da un'origine dati. Le query sono espresse in un linguaggio di query dedicato. Nel tempo sono stati sviluppati diversi linguaggi per i vari tipi di origini dati, ad esempio SQL per database relazionali e XQuery per XML. Lo sviluppatore di applicazioni deve pertanto imparare un nuovo linguaggio di query per ogni tipo di origine dati o formato dati supportato.

LINQ (Language-Integrated Query) semplifica la situazione offrendo un modello coerente per l'utilizzo dei dati con tutti i diversi tipi di origini e formati dati. In una query LINQ vengono utilizzati sempre gli oggetti. Vengono utilizzati gli stessi modelli di codifica di base per eseguire una query e trasformare i dati in documenti XML, database SQL, dataset ed entità ADO.NET, raccolte .NET Framework e qualsiasi altra origine o formato per cui sia disponibile un provider LINQ. In questo documento vengono illustrate le tre fasi della creazione e dell'utilizzo delle query LINQ di base.

Collegamento a video Per la dimostrazione video correlata, vedere Ricerca per categorie: Introduzione a LINQ.

Tre fasi di un'operazione di query

Le operazioni di query LINQ sono costituite da tre azioni:

  1. Ottenere l'origine o le origini dati.

  2. Creare la query.

  3. Eseguire la query.

In LINQ l'esecuzione di una query è distinta dalla creazione della query. I dati non vengono recuperati solo creando una query. Questo punto viene illustrato più dettagliatamente in seguito in questo argomento.

Nell'esempio riportato di seguito vengono illustrate le tre parti di un'operazione di query. Nell'esempio viene utilizzata una matrice di valori interi come pratica origine dati a mero scopo esemplificativo. Gli stessi concetti si applicano però anche ad altre origini dati.

Nota

In Pagina Compilazione, Progettazione progetti (Visual Basic), assicurarsi che Option Infer è impostato su In.

' Data source. 
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation. 
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution. 
For Each number In evensQuery
    Console.Write(number & " ")
Next

Output:

0 2 4 6

Origine dati

Poiché nell'esempio precedente è stata utilizzata una matrice come origine dati, viene supportata implicitamente l'interfaccia generica IEnumerable. Per questo motivo è possibile utilizzare una matrice come origine dati per una query LINQ. I tipi che supportano IEnumerable o un'interfaccia derivata come IQueryable generico sono denominati tipi queryable.

Come tipo queryable in modo implicito, la matrice non richiede alcuna modifica o trattamento speciale per essere utilizzata come origine dati LINQ. Lo stesso vale per qualsiasi tipo di raccolta che supporta IEnumerable, inclusi Listgenerico, Dictionarye altre classi nella libreria di classi.NET Framework.

Se i dati di origine non implementano IEnumerable, di un provider di LINQ è necessario per implementare la funzionalità degli operatori di query standard per l'origine dati. Ad esempio, LINQ to XML gestisce il caricamento di un documento XML in un tipo XElement queryable, come illustrato nell'esempio seguente. Per ulteriori informazioni sugli operatori di query standard, vedere Cenni preliminari sugli operatori di query standard.

' Create a data source from an XML document. 
Dim contacts = XElement.Load("c:\myContactList.xml")

Con LINQ to SQL è necessario creare prima un mapping relazionale a oggetti in fase di progettazione, manualmente o utilizzando Progettazione relazionale oggetti. È possibile quindi scrivere le query sugli oggetti e in fase di esecuzione LINQ to SQL gestisce la comunicazione con il database. Nell'esempio seguente customers rappresenta una tabella specifica nel database e Table supporta l'interfaccia generica IQueryable.

' Create a data source from a SQL table.
Dim db As New DataContext("C:\Northwind\Northwnd.mdf")
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)

Per ulteriori informazioni sulla creazione di tipi specifici di origini dati, vedere la documentazione dei diversi provider LINQ. Per un elenco di questi provider, vedere LINQ (Language-Integrated Query). La regola di base è semplice: un'origine dati LINQ è rappresentata da qualsiasi oggetto che supporti l'interfaccia generica IEnumerable o un'interfaccia da essa ereditata.

Nota

È inoltre possibile utilizzare come origini dati LINQ i tipi quali ArrayList, che supportano l'interfaccia non generica IEnumerable.Per un esempio che utilizza un oggetto ArrayList, vedere Procedura: eseguire una query su un ArrayList con LINQ.

Query

Nella query vengono specificate le informazioni da recuperare dall'origine o dalle origini dati. È inoltre possibile specificare il modo in cui ordinare, raggruppare o strutturare le informazioni prima che vengano restituite. Per consentire la creazione della query, Visual Basic ha incorporato una nuova sintassi della query nel linguaggio.

Quando viene eseguita, la query dell'esempio seguente restituisce tutti i numeri pari da una matrice di valori interi, numbers.

' Data source. 
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}

' Query creation. 
Dim evensQuery = From num In numbers
                 Where num Mod 2 = 0
                 Select num

' Query execution. 
For Each number In evensQuery
    Console.Write(number & " ")
Next

L'espressione di query contiene tre clausole: From, Where e Select. La funzione e lo scopo specifici di ogni clausola dell'espressione di query vengono illustrati in Operazioni di query di base (Visual Basic). Per ulteriori informazioni, vedere Query (Visual Basic). Tenere presente che in LINQ una definizione di query viene spesso archiviata in una variabile ed eseguita successivamente. La variabile di query, ad esempio evensQuery nell'esempio precedente, deve essere un tipo queryable. Il tipo di evensQuery è IEnumerable(Of Integer), assegnato dal compilatore mediante l'inferenza del tipo di variabile locale.

È importante tenere presente che la variabile di query stessa non effettua alcuna azione e non restituisce dati. Archivia solo la definizione della query. Nell'esempio precedente è il ciclo For Each che esegue la query.

Esecuzione della query

L'esecuzione della query è distinta dalla creazione della query. La creazione della query definisce la query, mentre l'esecuzione viene attivata da un meccanismo diverso. Una query può essere eseguita appena definita (esecuzione immediata) oppure è possibile archiviare la definizione ed eseguire la query in un secondo momento (esecuzione posticipata).

Esecuzione posticipata

Una tipica query LINQ è analoga a quella riportata nell'esempio precedente in cui è stata definita la variabile di query evensQuery. La query viene creata ma non eseguita immediatamente. La definizione della query viene invece archiviata nella variabile di query evensQuery. La query viene eseguita successivamente, in genere utilizzando un ciclo For Each che restituisce una sequenza di valori o applicando un operatore di query standard, ad esempio Count o Max. Questo processo viene denominato esecuzione posticipata.

' Query execution that results in a sequence of values. 
For Each number In evensQuery
    Console.Write(number & " ")
Next 

' Query execution that results in a single value. 
Dim evens = evensQuery.Count()

Per una sequenza di valori è possibile accedere ai dati recuperati utilizzando la variabile di iterazione nel ciclo For Each (number nell'esempio precedente). Poiché la variabile di query, evensQuery, contiene la definizione della query invece dei risultati della query, è possibile eseguire una query un numero illimitato di volte utilizzando la variabile di query più volte. Ad esempio, è possibile avere un database nell'applicazione che viene aggiornato continuamente mediante un'applicazione separata. Dopo avere creato una query che recupera i dati da tale database, è possibile utilizzare un ciclo For Each per eseguire ripetutamente la query, recuperando ogni volta i dati più recenti.

Nell'esempio seguente viene illustrato l'utilizzo dell'esecuzione posticipata. Dopo aver definito ed eseguito evensQuery2 con un ciclo For Each, come negli esempi precedenti, vengono modificati alcuni elementi nell'origine dati numbers. Un secondo ciclo For Each esegue quindi nuovamente evensQuery2. La seconda volta i risultati sono diversi, poiché il ciclo For Each esegue nuovamente la query utilizzando i nuovi valori di numbers.

Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}

Dim evensQuery2 = From num In numberArray
                  Where num Mod 2 = 0
                  Select num

Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8

' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
    Console.Write("  " & number)
Next
Console.WriteLine()

Output:

Evens in original array:

0 2 4 6

Evens in changed array:

0 10 2 22 8

Esecuzione immediata

Nell'esecuzione posticipata delle query la definizione della query viene archiviata in una variabile di query in modo da essere eseguita successivamente. Nell'esecuzione immediata la query viene eseguita al momento della definizione. L'esecuzione viene attivata quando si applica un metodo che richiede l'accesso ai singoli elementi del risultato della query. L'esecuzione immediata viene spesso forzata utilizzando uno degli operatori di query standard che restituiscono singoli valori, ad esempio Count, Max, Average e First. Questi operatori di query standard eseguono la query appena vengono applicati in modo da calcolare e restituire un risultato singleton. Per ulteriori informazioni sugli operatori di query standard che restituiscono singoli valori, vedere Operazioni di aggregazione, Operazioni sugli elementi e Operazioni del quantificatore.

Nella query seguente viene restituito un conteggio dei numeri pari in una matrice di valori interi. La definizione della query non viene salvata e numEvens è un semplice oggetto Integer.

Dim numEvens = (From num In numbers
                Where num Mod 2 = 0
                Select num).Count()

È possibile ottenere lo stesso risultato utilizzando il metodo Aggregate.

Dim numEvensAgg = Aggregate num In numbers
                  Where num Mod 2 = 0
                  Select num
                  Into Count()

È inoltre possibile forzare l'esecuzione di una query chiamando il metodo ToList o ToArray su una query (esecuzione immediata) o una variabile di query (esecuzione posticipata), come illustrato nel codice seguente.

' Immediate execution. 
Dim evensList = (From num In numbers
                 Where num Mod 2 = 0
                 Select num).ToList()

' Deferred execution. 
Dim evensQuery3 = From num In numbers
                  Where num Mod 2 = 0
                  Select num
' . . . 
Dim evensArray = evensQuery3.ToArray()

Negli esempi precedenti evensQuery3 è una variabile di query, mentre evensList è un elenco e evensArray è una matrice.

L'utilizzo di ToList o ToArray per forzare l'esecuzione immediata è particolarmente utile negli scenari in cui si desidera eseguire immediatamente la query e memorizzarne nella cache i risultati di un singolo oggetto della raccolta. Per ulteriori informazioni su tali metodi, vedere Conversione del tipo di dati.

È inoltre possibile eseguire una query utilizzando un metodo IEnumerable, ad esempio il metodo System#Collections#IEnumerable#GetEnumerator.

Dimostrazioni video correlate

Ricerca per categorie: Introduzione a LINQ

Procedura: scrittura di query in Visual Basic

Vedere anche

Attività

Esempi LINQ

Concetti

Cenni preliminari su Progettazione relazionale oggetti

Inferenza del tipo di variabile locale (Visual Basic)

Cenni preliminari sugli operatori di query standard

Introduzione a LINQ in Visual Basic

Altre risorse

Introduzione a LINQ in Visual Basic

LINQ in Visual Basic

Query (Visual Basic)