Relazioni tra i tipi nelle operazioni di query (Visual Basic)
Aggiornamento: novembre 2007
Le variabili utilizzate nelle operazioni di query LINQ (Language-Integrated Query) sono fortemente tipizzate e devono essere compatibili tra loro. La tipizzazione forte viene utilizzata nell'origine dati, nella query stessa e nell'esecuzione della query. Nella figura seguente vengono identificati i termini utilizzati per descrivere una query LINQ. Per ulteriori informazioni sulle parti di una query, vedere Operazioni di query di base (Visual Basic).
Parti di una query LINQ
Il tipo della variabile di intervallo nella query deve essere compatibile con il tipo degli elementi nell'origine dati. Il tipo della variabile di query deve essere compatibile con l'elemento della sequenza definito nella clausola Select. Infine, il tipo degli elementi della sequenza deve essere compatibile anche con il tipo della variabile di controllo del ciclo utilizzata nell'istruzione For Each che esegue la query. Questa tipizzazione forte semplifica l'identificazione degli errori di tipo in fase di compilazione.
In Visual Basic 2008 la tipizzazione forte viene applicata implementando l'inferenza del tipo di variabile locale, nota anche come tipizzazione implicita. Questa funzionalità viene utilizzata nell'esempio precedente e in tutti gli esempi e nella documentazione LINQ. In Visual Basic l'inferenza del tipo di variabile locale viene eseguita semplicemente utilizzando un'istruzione Dim senza una clausola As. Nell'esempio seguente city è fortemente tipizzato come stringa.
Dim city = "Seattle"
Nota: |
---|
L'inferenza del tipo di variabile locale funziona solo quando Option Infer è impostato su On. Per ulteriori informazioni, vedere Istruzione Option Infer. |
Tuttavia, anche se si utilizza l'inferenza del tipo di variabile locale in una query, le stesse relazioni tra i tipi sono presenti tra le variabili nell'origine dati, la variabile di query e il ciclo di esecuzione della query. È utile avere una comprensione di base di queste relazioni tra i tipi quando si scrivono le query LINQ o si utilizzano gli esempi e gli esempi di codice presenti nella documentazione.
Query che restituiscono elementi dell'origine dati completi
Nell'esempio seguente viene illustrata un'operazione di query LINQ che restituisce una sequenza di elementi selezionati dai dati di origine. Il database di origine, names, contiene una matrice di stringhe e il risultato della query è una sequenza contenente stringhe che iniziano con la lettera M.
Dim names = New String() {"John", "Rick", "Maggie", "Mary"}
Dim mNames = From name In names _
Where name.IndexOf("M") = 0 _
Select name
For Each nm In mNames
Console.WriteLine(nm)
Next
Questo equivale al codice seguente, ma è molto più breve e facile da scrivere. L'utilizzo dell'inferenza del tipo di variabile locale nelle query è lo stile preferito in Visual Basic.
Dim names2() As String = {"John", "Rick", "Maggie", "Mary"}
Dim mNames2 As IEnumerable(Of String) = _
From name As String In names _
Where name.IndexOf("M") = 0 _
Select name
For Each nm As String In mNames
Console.WriteLine(nm)
Next
Le relazioni riportate di seguito sono presenti in entrambi gli esempi di codice precedenti, indipendentemente dal fatto che i tipi vengano determinati in modo implicito o esplicito.
Il tipo degli elementi nell'origine dati, names, è il tipo della variabile di intervallo, name, nella query.
Il tipo dell'oggetto selezionato, name, determina il tipo della variabile di query mNames. In questo caso name è una stringa, pertanto la variabile di query è IEnumerable(Of String) in Visual Basic.
La query definita in mNames viene eseguita nel ciclo For Each. Il ciclo scorre il risultato dell'esecuzione della query. Poiché mNames, quando viene eseguito, restituisce una sequenza di stringhe, anche la variabile di iterazione del ciclo, nm, è una stringa.
Query che restituiscono un campo dagli elementi selezionati
Nell'esempio seguente viene illustrata un'operazione di query LINQ to SQL che restituisce una sequenza contenente solo una parte di ogni elemento selezionato dall'origine dati. La query utilizza un insieme di oggetti Customer come origine dati e proietta solo la proprietà Name nel risultato. Poiché il nome cliente è una stringa, la query genera una sequenza di stringhe come output.
' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim custNames = From cust In customers _
Where cust.City = "London" _
Select cust.Name
For Each custName In custNames
Console.WriteLine(custName)
Next
Le relazioni tra le variabili sono simili a quelle riportate nell'esempio più semplice.
Il tipo degli elementi nell'origine dati, customers, è il tipo della variabile di intervallo, cust, nella query. In questo esempio, il tipo è Customer.
L'istruzione Select restituisce la proprietà Name di ogni oggetto Customer anziché l'intero oggetto. Poiché Name è una stringa, la variabile di query, custNames, sarà di nuovo IEnumerable(Of String), non Customer.
Poiché custNames rappresenta una sequenza di stringhe, la variabile di iterazione del ciclo For Each, custName, deve essere una stringa.
Senza l'inferenza del tipo di variabile locale, l'esempio precedente risulterebbe più complesso da scrivere e da comprendere, come illustrato nell'esempio seguente.
' Method GetTable returns a table of Customer objects.
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)()
Dim custNames As IEnumerable(Of String) = _
From cust As Customer In customers _
Where cust.City = "London" _
Select cust.Name
For Each custName As String In custNames
Console.WriteLine(custName)
Next
Query che richiedono tipi anonimi
Nell'esempio seguente viene illustrata una situazione più complessa. Nell'esempio precedente non era utile specificare i tipi per tutte le variabili in modo esplicito. In questo esempio non è possibile. Anziché selezionare gli elementi Customer completi dall'origine dati o un singolo campo da ogni elemento, la clausola Select in questa query restituisce due proprietà dell'oggetto Customer originale: Name e City. In risposta alla clausola Select, il compilatore definisce un tipo anonimo che contiene quelle due proprietà. Il risultato dell'esecuzione di nameCityQuery nel ciclo For Each è un insieme di istanze del nuovo tipo anonimo. Poiché il tipo anonimo non ha un nome utilizzabile, non è possibile specificare il tipo di nameCityQuery o custInfo in modo esplicito. Ovvero, con un tipo anonimo non è disponibile alcun nome del tipo da utilizzare al posto di String in IEnumerable(Of String). Per ulteriori informazioni, vedere Tipi anonimi.
' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim nameCityQuery = From cust In customers _
Where cust.City = "London" _
Select cust.Name, cust.City
For Each custInfo In nameCityQuery
Console.WriteLine(custInfo.Name)
Next
Anche se non è possibile specificare i tipi per tutte le variabili nell'esempio precedente, le relazioni restano invariate.
Il tipo degli elementi nell'origine dati è ancora una volta il tipo della variabile di intervallo nella query. In questo esempio cust è un'istanza di Customer.
Poiché l'istruzione Select genera un tipo anonimo, la variabile di query, nameCityQuery, deve essere tipizzata in modo implicito come tipo anonimo. Un tipo anonimo non ha un nome utilizzabile e pertanto non può essere specificato in modo esplicito.
Il tipo della variabile di iterazione nel ciclo For Each è il tipo anonimo creato nel passaggio 2. Poiché il tipo non ha un nome utilizzabile, il tipo della variabile di iterazione del ciclo deve essere determinato in modo implicito.
Vedere anche
Concetti
Introduzione a LINQ in Visual Basic