Condividi tramite


Creare la tua prima query LINQ (Visual Basic)

Una query è un'espressione che recupera i dati da un'origine dati. Le query vengono espresse in un linguaggio di query dedicato. Nel corso del tempo sono stati sviluppati linguaggi diversi per diversi tipi di origini dati, ad esempio SQL per i database relazionali e XQuery per XML. Ciò rende necessario allo sviluppatore dell'applicazione di apprendere un nuovo linguaggio di query per ogni tipo di origine dati o formato di dati supportato.

Language-Integrated Query (LINQ) semplifica la situazione offrendo un modello coerente per l'uso dei dati in vari tipi di origini dati e formati. In una query LINQ si lavora sempre con gli oggetti . Si usano gli stessi modelli di codifica di base per eseguire query e trasformare i dati in documenti XML, database SQL, ADO.NET set di dati ed entità, raccolte .NET Framework e qualsiasi altra origine o formato per cui è disponibile un provider LINQ. Questo documento descrive le tre fasi della creazione e dell'uso di query LINQ di base.

Le tre fasi di un'operazione di interrogazione

Le operazioni di query LINQ sono costituite da tre azioni:

  1. Ottenere l'origine o le origini dei dati.

  2. Creare la query.

  3. Esecuzione della query.

In LINQ l'esecuzione di una query è diversa dalla creazione della query. Non si recuperano dati semplicemente creando una query. Questo punto viene illustrato in modo più dettagliato più avanti in questo argomento.

Nell'esempio seguente vengono illustrate le tre parti di un'operazione di query. Nell'esempio viene usata una matrice di numeri interi come origine dati utile a scopo dimostrativo. Tuttavia, gli stessi concetti si applicano anche ad altre origini dati.

Annotazioni

Nella pagina Compilazione Progettazione (Visual Basic) verificare che Option infer sia impostato su Attivato.

' 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

Risultato:

0 2 4 6

La origine dati

Poiché l'origine dati nell'esempio precedente è una matrice, supporta in modo implicito l'interfaccia generica IEnumerable<T> . Questo è il fatto che consente di usare una matrice come origine dati per una query LINQ. I tipi che supportano IEnumerable<T> o un'interfaccia derivata, ad esempio il generico IQueryable<T> , sono denominati tipi queryable.

Come tipo querybile in modo implicito, la matrice non richiede alcuna modifica o un trattamento speciale per fungere da origine dati LINQ. Lo stesso vale per qualsiasi tipo di raccolta che supporta IEnumerable<T>, incluse le classi generiche List<T>, Dictionary<TKey,TValue>e altre classi nella libreria di classi .NET Framework.

Se i dati di origine non implementano già IEnumerable<T>, è necessario un provider LINQ per implementare la funzionalità degli operatori di query standard per tale origine dati. Ad esempio, LINQ to XML gestisce il lavoro di caricamento di un documento XML in un tipo queryable XElement , come illustrato nell'esempio seguente. Per altre informazioni sugli operatori di query standard, vedere Panoramica degli operatori di query standard (Visual Basic).

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

Con LINQ to SQL, si crea prima di tutto un mapping relazionale a oggetti in fase di progettazione, manualmente o usando LINQ to SQL Tools in Visual Studio in Visual Studio . Le query vengono scritte sugli oggetti e in fase di esecuzione LINQ to SQL gestisce la comunicazione con il database. Nell'esempio seguente rappresenta customers una tabella specifica nel database e Table<TEntity> supporta l'oggetto generico IQueryable<T>.

' 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 altre informazioni su come creare tipi specifici di origini dati, vedere la documentazione per i vari provider LINQ. Per un elenco di questi provider, vedere LINQ (Language-Integrated Query).) La regola di base è semplice: un'origine dati LINQ è qualsiasi oggetto che supporta l'interfaccia generica IEnumerable<T> o un'interfaccia che eredita da essa.

Annotazioni

I tipi come ArrayList quelli che supportano l'interfaccia non generica IEnumerable possono essere usati anche come origini dati LINQ. Per un esempio che usa un ArrayList, vedere Procedura: Eseguire query su un ArrayList con LINQ (Visual Basic).

The Query

Nella query, specifichi quali informazioni vuoi recuperare dall'origine o dalle origini dati. È anche possibile specificare la modalità di ordinamento, raggruppamento o struttura delle informazioni prima che vengano restituite. Per abilitare la creazione di query, Visual Basic include una nuova sintassi di query nel linguaggio.

Quando viene eseguita, la query nell'esempio seguente restituisce tutti i numeri pari di una matrice integer, 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, Wheree Select. Le funzioni e gli scopi specifici di ogni clausola di espressione di query sono discusse in Operazioni di base delle query (Visual Basic). Per altre informazioni, vedere Query. Si noti che in LINQ una definizione di query viene spesso archiviata in una variabile ed eseguita in un secondo momento. 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 usando l'inferenza del tipo locale.

È importante ricordare che la variabile di query stessa non esegue alcuna azione e non restituisce dati. Archivia solo la definizione della query. Nell'esempio precedente si tratta del For Each ciclo che esegue la query.

Esecuzione di query

L'esecuzione delle query è separata dalla creazione di query. La creazione della query ne definisce i dettagli, ma l'esecuzione è attivata da un meccanismo differente. Una query può essere eseguita non appena viene definita (esecuzione immediata) oppure la definizione può essere archiviata e la query può essere eseguita in un secondo momento (esecuzione posticipata).

Esecuzione posticipata

Una tipica query LINQ è simile a quella dell'esempio precedente, in cui evensQuery è definita. Crea la query ma non la esegue immediatamente. Invece, la definizione della query viene archiviata nella variabile di query evensQuery. La query viene eseguita in un secondo momento, in genere usando un For Each ciclo , che restituisce una sequenza di valori o applicando un operatore di query standard, ad esempio Count o Max. Questo processo viene definito 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, si accede ai dati recuperati usando la variabile di iterazione nel For Each ciclo (number nell'esempio precedente). Poiché la variabile di query, evensQuery, contiene la definizione di query anziché i risultati della query, è possibile eseguire una query con la frequenza desiderata usando la variabile di query più volte. Ad esempio, potrebbe essere presente un database nell'applicazione che viene aggiornato continuamente da un'applicazione separata. Dopo aver creato una query che recupera i dati da tale database, è possibile usare un For Each ciclo per eseguire ripetutamente la query, recuperando i dati più recenti ogni volta.

Nell'esempio seguente viene illustrato il funzionamento dell'esecuzione posticipata. Dopo che evensQuery2 è stato definito ed eseguito con un ciclo For Each, come negli esempi precedenti, alcuni elementi nella sorgente dati numbers vengono modificati. Quindi viene eseguito For Each di nuovo un secondo evensQuery2 ciclo. I risultati sono diversi la seconda volta, perché il For Each ciclo esegue di nuovo la query, usando i nuovi valori in 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()

Risultato:

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 per un'esecuzione successiva. Nell'esecuzione immediata, la query viene eseguita al momento della relativa definizione. L'esecuzione viene attivata quando si applica un metodo che richiede l'accesso a singoli elementi del risultato della query. L'esecuzione immediata viene spesso forzata usando uno degli operatori di query standard che restituiscono valori singoli. Gli esempi sono Count, MaxAverage, e First. Questi operatori di query standard eseguono la query non appena vengono applicati per calcolare e restituire un risultato singleton. Per altre informazioni sugli operatori di query standard che restituiscono valori singoli, vedere Operazioni di aggregazione, Operazioni sugli elementi e Operazioni quantificatori.

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

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

È possibile ottenere lo stesso risultato usando il Aggregate metodo .

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

È anche possibile forzare l'esecuzione di una query chiamando il ToList metodo o ToArray su una query (immediata) o una variabile di query (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, ma evensList è un elenco ed evensArray è una matrice.

L'uso di ToList o ToArray per forzare l'esecuzione immediata è particolarmente utile negli scenari in cui si vuole eseguire la query immediatamente e memorizzare i risultati nella cache in un singolo oggetto collezione. Per altre informazioni su questi metodi, vedere Conversione di tipi di dati.

È anche possibile eseguire una query usando un IEnumerable metodo, ad esempio il IEnumerable.GetEnumerator metodo .

Vedere anche