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) aggiunge funzionalità di query a Visual Basic e offre funzionalità semplici e potenti quando si lavora con tutti i tipi di dati. Anziché inviare una query a un database da elaborare o usare una sintassi di query diversa per ogni tipo di dati che si sta cercando, LINQ introduce query come parte del linguaggio Visual Basic. Usa una sintassi unificata indipendentemente dal tipo di dati.
LINQ consente di eseguire query sui dati da un database di SQL Server, XML, matrici e raccolte in memoria, set di dati ADO.NET, o da qualsiasi altra origine dati remota o locale che supporti LINQ. È possibile eseguire questa operazione con gli elementi comuni del linguaggio Visual Basic. Poiché le query vengono scritte nel linguaggio Visual Basic, i risultati della query vengono restituiti come oggetti fortemente tipizzati. Questi oggetti supportano IntelliSense, che consente di scrivere codice più velocemente e intercettare gli errori nelle query in fase di compilazione anziché in fase di esecuzione. Le query LINQ possono essere usate come origine di query aggiuntive per perfezionare i risultati. Possono anche essere associati ai controlli in modo che gli utenti possano visualizzare e modificare facilmente i risultati della query.
Ad esempio, l'esempio di codice seguente mostra una query LINQ che restituisce un elenco di clienti da una raccolta e li raggruppa in base alla posizione.
' Obtain a list of customers.
Dim customers As List(Of Customer) = GetCustomers()
' Return customers that are grouped based on country.
Dim countries = From cust In customers
Order By cust.Country, cust.City
Group By CountryName = cust.Country
Into CustomersInCountry = Group, Count()
Order By CountryName
' Output the results.
For Each country In countries
Debug.WriteLine(country.CountryName & " count=" & country.Count)
For Each customer In country.CustomersInCountry
Debug.WriteLine(" " & customer.CompanyName & " " & customer.City)
Next
Next
' Output:
' Canada count=2
' Contoso, Ltd Halifax
' Fabrikam, Inc. Vancouver
' United States count=1
' Margie's Travel Redmond
Esecuzione degli esempi
Per eseguire gli esempi nell'introduzione e nella sezione Struttura di una query LINQ , includere il codice seguente, che restituisce elenchi di clienti e ordini.
' Return a list of customers.
Private Function GetCustomers() As List(Of Customer)
Return New List(Of Customer) From
{
New Customer With {.CustomerID = 1, .CompanyName = "Contoso, Ltd", .City = "Halifax", .Country = "Canada"},
New Customer With {.CustomerID = 2, .CompanyName = "Margie's Travel", .City = "Redmond", .Country = "United States"},
New Customer With {.CustomerID = 3, .CompanyName = "Fabrikam, Inc.", .City = "Vancouver", .Country = "Canada"}
}
End Function
' Return a list of orders.
Private Function GetOrders() As List(Of Order)
Return New List(Of Order) From
{
New Order With {.CustomerID = 1, .Amount = "200.00"},
New Order With {.CustomerID = 3, .Amount = "600.00"},
New Order With {.CustomerID = 1, .Amount = "300.00"},
New Order With {.CustomerID = 2, .Amount = "100.00"},
New Order With {.CustomerID = 3, .Amount = "800.00"}
}
End Function
' Customer Class.
Private Class Customer
Public Property CustomerID As Integer
Public Property CompanyName As String
Public Property City As String
Public Property Country As String
End Class
' Order Class.
Private Class Order
Public Property CustomerID As Integer
Public Property Amount As Decimal
End Class
Provider di LINQ
Un provider LINQ mappa le query LINQ di Visual Basic all'origine dati interrogata. Quando si scrive una query LINQ, il provider accetta tale query e lo converte in comandi che l'origine dati sarà in grado di eseguire. Il provider converte anche i dati dall'origine agli oggetti che costituiscono il risultato della query. Infine, converte gli oggetti in dati quando si inviano aggiornamenti all'origine dati.
Visual Basic include i seguenti provider LINQ.
Fornitore | Descrizione |
---|---|
LINQ to Objects | Il provider LINQ to Objects consente di eseguire query su raccolte e matrici in memoria. Se un oggetto supporta l'interfaccia IEnumerable o IEnumerable<T> , il provider LINQ to Objects consente di eseguire query su di esso. È possibile abilitare il provider LINQ to Objects importando lo System.Linq spazio dei nomi importato per impostazione predefinita per tutti i progetti Visual Basic. Per altre informazioni sul provider LINQ to Objects, vedere LINQ to Objects. |
LINQ to SQL | Il provider LINQ to SQL consente di eseguire query e modificare i dati in un database di SQL Server. In questo modo è facile eseguire il mapping del modello a oggetti per un'applicazione alle tabelle e agli oggetti in un database. Visual Basic semplifica l'uso di LINQ to SQL includendo Progettazione relazionale oggetti (O/R Designer). Questo strumento di progettazione viene usato per creare un modello a oggetti in un'applicazione che mappa a oggetti in un database. Il progettista O/R fornisce anche funzionalità per eseguire il mapping delle stored procedure e funzioni all'oggetto DataContext, che gestisce la comunicazione con il database e archivia lo stato per i controlli di concorrenza ottimistica. Per altre informazioni sul provider LINQ to SQL, vedere LINQ to SQL. Per altre informazioni su Progettazione relazionale oggetti, vedere LINQ to SQL Tools in Visual Studio. |
LINQ to XML | Il provider LINQ to XML consente di eseguire query e modificare XML. È possibile modificare il codice XML in memoria oppure caricare xml da e salvare XML in un file. Inoltre, il provider LINQ to XML consente valori letterali XML e proprietà dell'asse XML che consentono di scrivere XML direttamente nel codice Visual Basic. Per altre informazioni, vedere XML. |
LINQ to DataSet | Il provider LINQ to DataSet consente di eseguire query e aggiornare i dati in un set di dati ADO.NET. È possibile aggiungere la potenza di LINQ alle applicazioni che usano set di dati per semplificare ed estendere le funzionalità per l'esecuzione di query, l'aggregazione e l'aggiornamento dei dati nel set di dati. Per altre informazioni, vedere LINQ to DataSet. |
Struttura di una query LINQ
Una query LINQ, spesso definita espressione di query, è costituita da una combinazione di clausole di query che identificano le origini dati e le variabili di iterazione per la query. Un'espressione di query può includere anche istruzioni per l'ordinamento, il filtro, il raggruppamento e il join o i calcoli da applicare ai dati di origine. La sintassi dell'espressione di query è simile alla sintassi di SQL; pertanto, si potrebbe trovare gran parte della sintassi familiare.
Un'espressione di query inizia con una From
clausola . Questa clausola identifica i dati di origine per una query e le variabili usate per fare riferimento a ogni elemento dei dati di origine singolarmente. Queste variabili sono denominate variabili di intervallo o variabili di iterazione. La From
clausola è obbligatoria per una query, ad eccezione Aggregate
delle query, in cui la From
clausola è facoltativa. Dopo aver identificato l'ambito e l'origine della query nelle From
clausole o Aggregate
, è possibile includere qualsiasi combinazione di clausole di query per perfezionare la query. Per informazioni dettagliate sulle clausole di query, vedere Operatori di query LINQ di Visual Basic più avanti in questo argomento. Ad esempio, la query seguente identifica una raccolta di origine di dati del cliente come customers
variabile e una variabile di iterazione denominata cust
.
Dim customers = GetCustomers()
Dim queryResults = From cust In customers
For Each result In queryResults
Debug.WriteLine(result.CompanyName & " " & result.Country)
Next
' Output:
' Contoso, Ltd Canada
' Margie's Travel United States
' Fabrikam, Inc. Canada
Questo esempio è una query valida da sola; Tuttavia, la query diventa molto più potente quando si aggiungono più clausole di query per perfezionare il risultato. Ad esempio, è possibile aggiungere una Where
clausola per filtrare il risultato in base a uno o più valori. Le espressioni di query sono una singola riga di codice; è sufficiente aggiungere clausole di query aggiuntive alla fine della query. È possibile suddividere una query su più righe di testo per migliorare la leggibilità usando il carattere di sottolineatura (_) di continuazione della riga. Nell'esempio di codice seguente viene illustrato un esempio di query che include una Where
clausola .
Dim queryResults = From cust In customers
Where cust.Country = "Canada"
Un'altra clausola di query avanzata è la Select
clausola , che consente di restituire solo i campi selezionati dall'origine dati. Le query LINQ restituiscono raccolte enumerabili di oggetti fortemente tipizzati. Una query può restituire una raccolta di tipi anonimi o tipi denominati. È possibile utilizzare la Select
clausola per restituire solo un singolo campo dall'origine dati. Quando si esegue questa operazione, il tipo della raccolta restituita è il tipo di tale singolo campo. È anche possibile usare la Select
clausola per restituire più campi dall'origine dati. Quando si esegue questa operazione, il tipo della raccolta restituita è un nuovo tipo anonimo. È anche possibile associare i campi restituiti dalla query ai campi di un tipo denominato specificato. Nell'esempio di codice seguente viene illustrata un'espressione di query che restituisce una raccolta di tipi anonimi con membri popolati con dati dai campi selezionati dall'origine dati.
Dim queryResults = From cust In customers
Where cust.Country = "Canada"
Select cust.CompanyName, cust.Country
Le query LINQ possono essere usate anche per combinare più origini di dati e restituire un singolo risultato. Questa operazione può essere eseguita con una o più From
clausole oppure usando le Join
clausole di query o Group Join
. Nell'esempio di codice seguente viene illustrata un'espressione di query che combina i dati del cliente e dell'ordine e restituisce una raccolta di tipi anonimi contenenti dati relativi a clienti e ordini.
Dim customers = GetCustomers()
Dim orders = GetOrders()
Dim queryResults = From cust In customers, ord In orders
Where cust.CustomerID = ord.CustomerID
Select cust, ord
For Each result In queryResults
Debug.WriteLine(result.ord.Amount & " " & result.ord.CustomerID & " " & result.cust.CompanyName)
Next
' Output:
' 200.00 1 Contoso, Ltd
' 300.00 1 Contoso, Ltd
' 100.00 2 Margie's Travel
' 600.00 3 Fabrikam, Inc.
' 800.00 3 Fabrikam, Inc.
È possibile usare la Group Join
clausola per creare un risultato di query gerarchico contenente una raccolta di oggetti cliente. Ogni oggetto cliente ha una proprietà che contiene una raccolta di tutti gli ordini di quel cliente. Nell'esempio di codice seguente viene illustrata un'espressione di query che combina i dati dei clienti e degli ordini come risultato gerarchico e restituisce una raccolta di tipi anonimi. La query restituisce un tipo che include una CustomerOrders
proprietà che contiene una raccolta di dati sugli ordini per il cliente. Include anche una OrderTotal
proprietà che contiene la somma dei totali per tutti gli ordini per il cliente. Questa query è equivalente a un LEFT OUTER JOIN (una modalità di combinazione esterna a sinistra).
Dim customers = GetCustomers()
Dim orders = GetOrders()
Dim queryResults = From cust In customers
Group Join ord In orders On
cust.CustomerID Equals ord.CustomerID
Into CustomerOrders = Group,
OrderTotal = Sum(ord.Amount)
Select cust.CompanyName, cust.CustomerID,
CustomerOrders, OrderTotal
For Each result In queryResults
Debug.WriteLine(result.OrderTotal & " " & result.CustomerID & " " & result.CompanyName)
For Each ordResult In result.CustomerOrders
Debug.WriteLine(" " & ordResult.Amount)
Next
Next
' Output:
' 500.00 1 Contoso, Ltd
' 200.00
' 300.00
' 100.00 2 Margie's Travel
' 100.00
' 1400.00 3 Fabrikam, Inc.
' 600.00
' 800.00
Esistono diversi operatori di query LINQ aggiuntivi che è possibile usare per creare espressioni di query avanzate. Nella sezione successiva di questo argomento vengono illustrate le varie clausole di query che è possibile includere in un'espressione di query. Per informazioni dettagliate sulle clausole di query di Visual Basic, vedere Query.
Operatori di query LINQ di Visual Basic
Le classi nello System.Linq spazio dei nomi e negli altri spazi dei nomi che supportano le query LINQ includono metodi che è possibile chiamare per creare e perfezionare le query in base alle esigenze dell'applicazione. Visual Basic include parole chiave per le clausole di query comuni seguenti. Per informazioni dettagliate sulle clausole di query di Visual Basic, vedere Query.
Clausola FROM
Per avviare una query, è necessaria una From
clausola o una Aggregate
clausola. Una From
clausola specifica una raccolta di origine e una variabile di iterazione per una query. Per esempio:
' Returns the company name for all customers for which
' the Country is equal to "Canada".
Dim names = From cust In customers
Where cust.Country = "Canada"
Select cust.CompanyName
Clausola SELECT
Opzionale. Una Select
clausola dichiara un set di variabili di iterazione per una query. Per esempio:
' Returns the company name and ID value for each
' customer as a collection of a new anonymous type.
Dim customerList = From cust In customers
Select cust.CompanyName, cust.CustomerID
Se non viene specificata una Select
clausola, le variabili di iterazione per la query sono costituite dalle variabili di iterazione specificate dalla From
clausola o Aggregate
.
Condizione Where
Opzionale. Una Where
clausola specifica una condizione di filtro per una query. Per esempio:
' Returns all product names for which the Category of
' the product is "Beverages".
Dim names = From product In products
Where product.Category = "Beverages"
Select product.Name
Clausola Ordina Per
Opzionale. Una Order By
clausola specifica l'ordine di ordinamento per le colonne in una query. Per esempio:
' Returns a list of books sorted by price in
' ascending order.
Dim titlesAscendingPrice = From b In books
Order By b.price
Clausola Join
Opzionale. Una Join
clausola combina due raccolte in una singola raccolta. Per esempio:
' Returns a combined collection of all of the
' processes currently running and a descriptive
' name for the process taken from a list of
' descriptive names.
Dim processes = From proc In Process.GetProcesses
Join desc In processDescriptions
On proc.ProcessName Equals desc.ProcessName
Select proc.ProcessName, proc.Id, desc.Description
Clausola Group By
Opzionale. Una Group By
clausola raggruppa gli elementi di un risultato di una query. Può essere usato per applicare funzioni di aggregazione a ogni gruppo. Per esempio:
' Returns a list of orders grouped by the order date
' and sorted in ascending order by the order date.
Dim orderList = From order In orders
Order By order.OrderDate
Group By OrderDate = order.OrderDate
Into OrdersByDate = Group
Clausola Unione di Gruppo
Opzionale. Una Group Join
clausola combina due raccolte in una singola raccolta gerarchica. Per esempio:
' Returns a combined collection of customers and
' customer orders.
Dim customerList = From cust In customers
Group Join ord In orders On
cust.CustomerID Equals ord.CustomerID
Into CustomerOrders = Group,
TotalOfOrders = Sum(ord.Amount)
Select cust.CompanyName, cust.CustomerID,
CustomerOrders, TotalOfOrders
Clausola di aggregazione
Per avviare una query, è necessaria una Aggregate
clausola o una From
clausola . Una Aggregate
clausola applica una o più funzioni di aggregazione a una raccolta. Ad esempio, è possibile utilizzare la Aggregate
clausola per calcolare una somma per tutti gli elementi restituiti da una query, come nell'esempio seguente.
' Returns the sum of all order amounts.
Dim orderTotal = Aggregate order In orders
Into Sum(order.Amount)
È anche possibile usare la Aggregate
clausola per modificare una query. Ad esempio, è possibile usare la Aggregate
clausola per eseguire un calcolo su una raccolta di query correlata. Per esempio:
' Returns the customer company name and largest
' order amount for each customer.
Dim customerMax = From cust In customers
Aggregate order In cust.Orders
Into MaxOrder = Max(order.Amount)
Select cust.CompanyName, MaxOrder
Clausola Let
Opzionale. Una Let
clausola calcola un valore e la assegna a una nuova variabile nella query. Per esempio:
' Returns a list of products with a calculation of
' a ten percent discount.
Dim discountedProducts = From prod In products
Let Discount = prod.UnitPrice * 0.1
Where Discount >= 50
Select prod.Name, prod.UnitPrice, Discount
Clausola Distinta
Opzionale. Una Distinct
clausola limita i valori della variabile di iterazione corrente per eliminare i valori duplicati nei risultati della query. Per esempio:
' Returns a list of cities with no duplicate entries.
Dim cities = From item In customers
Select item.City
Distinct
Clausola Skip
Opzionale. Una Skip
clausola ignora un numero specificato di elementi in una raccolta e quindi restituisce gli elementi rimanenti. Per esempio:
' Returns a list of customers. The first 10 customers
' are ignored and the remaining customers are
' returned.
Dim customerList = From cust In customers
Skip 10
Clausola Salta Finché
Opzionale. Una Skip While
clausola ignora gli elementi di una raccolta purché una condizione specificata sia true
e restituisca gli elementi rimanenti. Per esempio:
' Returns a list of customers. The query ignores all
' customers until the first customer for whom
' IsSubscriber returns false. That customer and all
' remaining customers are returned.
Dim customerList = From cust In customers
Skip While IsSubscriber(cust)
Clausola di Accettazione
Opzionale. Una Take
clausola restituisce un numero specificato di elementi contigui dall'inizio di una raccolta. Per esempio:
' Returns the first 10 customers.
Dim customerList = From cust In customers
Take 10
Clausola Take While
Opzionale. Una Take While
clausola include elementi in una raccolta purché una condizione specificata sia true
e ignori gli elementi rimanenti. Per esempio:
' Returns a list of customers. The query returns
' customers until the first customer for whom
' HasOrders returns false. That customer and all
' remaining customers are ignored.
Dim customersWithOrders = From cust In customers
Order By cust.Orders.Count Descending
Take While HasOrders(cust)
Usare funzionalità aggiuntive per le query LINQ
È possibile usare funzionalità di query LINQ aggiuntive chiamando i membri dei tipi enumerabili e queryable forniti da LINQ. È possibile usare queste funzionalità aggiuntive chiamando un particolare operatore di query sul risultato di un'espressione di query. Nell'esempio seguente viene usato il metodo Enumerable.Union per combinare i risultati di due query in un risultato della query. Usa il Enumerable.ToList metodo per restituire il risultato della query come elenco generico.
Public Function GetAllCustomers() As List(Of Customer)
Dim customers1 = From cust In domesticCustomers
Dim customers2 = From cust In internationalCustomers
Dim customerList = customers1.Union(customers2)
Return customerList.ToList()
End Function
Per informazioni dettagliate sulle funzionalità LINQ aggiuntive, vedere Panoramica degli operatori di query standard.
Connettersi a un database usando LINQ to SQL
In Visual Basic si identificano gli oggetti di database di SQL Server, ad esempio tabelle, viste e stored procedure, a cui si vuole accedere usando un file LINQ to SQL. Un file LINQ to SQL ha un'estensione dbml.
Quando si dispone di una connessione valida a un database di SQL Server, è possibile aggiungere un modello di elemento LINQ to SQL Classes al progetto. Verrà visualizzata la finestra di progettazione relazionale oggetti (progettazione O/R). Il Progettista O/R consente di trascinare gli elementi a cui si desidera accedere nel codice dall'Esplora server o dall'Esplora database sulla superficie di progettazione. Il file LINQ to SQL aggiunge un DataContext oggetto al progetto. Questo oggetto include proprietà e raccolte per le tabelle e le viste a cui si desidera accedere e i metodi per le stored procedure che si desidera chiamare. Dopo aver salvato le modifiche apportate al file LINQ to SQL (con estensione dbml), è possibile accedere a questi oggetti nel codice facendo riferimento all'oggetto DataContext definito da O/R Designer. L'oggetto DataContext per il progetto è denominato in base al nome del file LINQ to SQL. Ad esempio, un file LINQ to SQL denominato Northwind.dbml creerà un DataContext oggetto denominato NorthwindDataContext
.
Per esempi con istruzioni dettagliate, vedere Procedura: Eseguire query su un database e Procedura: Chiamare una stored procedure.
Funzionalità di Visual Basic che supportano LINQ
Visual Basic include altre funzionalità rilevanti che semplificano l'uso di LINQ e riducono la quantità di codice da scrivere per eseguire query LINQ. Questi includono:
Tipi anonimi, che consentono di creare un nuovo tipo in base a un risultato della query.
Variabili tipizzate in modo implicito, che consentono di rinviare la specifica di un tipo e consentire al compilatore di dedurre il tipo in base al risultato della query.
Metodi di estensione, che consentono di estendere un tipo esistente con metodi personalizzati senza modificare il tipo stesso.
Per informazioni dettagliate, vedere Funzionalità di Visual Basic che supportano LINQ.
Esecuzione di query posticipata e immediata
L'esecuzione delle query è separata dalla creazione di una query. Dopo la creazione di una query, l'esecuzione viene attivata da un meccanismo separato. 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).
Per impostazione predefinita, quando si crea una query, la query stessa non viene eseguita immediatamente. La definizione della query viene invece archiviata nella variabile usata per fare riferimento al risultato della query. Quando si accede alla variabile dei risultati della query in un secondo momento nel codice, ad esempio in un For…Next
ciclo, la query viene eseguita. Questo processo viene definito esecuzione posticipata.
Le query possono essere eseguite anche quando vengono definite, definite come esecuzione immediata. È possibile attivare l'esecuzione immediata applicando un metodo che richiede l'accesso a singoli elementi del risultato della query. Può trattarsi del risultato dell'inclusione di una funzione di aggregazione, ad esempio Count
, Sum
, Average
Min
, o Max
. Per altre informazioni sulle funzioni di aggregazione, vedere Clausola di aggregazione.
L'uso dei metodi ToList
o ToArray
forzerà anche l'esecuzione immediata. Ciò può essere utile quando si vuole eseguire la query immediatamente e memorizzare nella cache i risultati. Per altre informazioni su questi metodi, vedere Conversione di tipi di dati.
Per altre informazioni sull'esecuzione di query, vedere Scrittura della prima query LINQ.
XML in Visual Basic
Le funzionalità XML in Visual Basic includono valori letterali XML e proprietà dell'asse XML, che consentono di creare, accedere, eseguire query e modificare facilmente xml nel codice. I valori letterali XML consentono di scrivere codice XML direttamente nel codice. Il compilatore Visual Basic considera il codice XML come oggetto dati di prima classe.
Nell'esempio di codice seguente viene illustrato come creare un elemento XML, accedere ai relativi sottoelementi e attributi ed eseguire query sul contenuto dell'elemento usando LINQ.
' Place Imports statements at the top of your program.
Imports <xmlns:ns="http://SomeNamespace">
Module Sample1
Sub SampleTransform()
' Create test by using a global XML namespace prefix.
Dim contact =
<ns:contact>
<ns:name>Patrick Hines</ns:name>
<ns:phone ns:type="home">206-555-0144</ns:phone>
<ns:phone ns:type="work">425-555-0145</ns:phone>
</ns:contact>
Dim phoneTypes =
<phoneTypes>
<%= From phone In contact.<ns:phone>
Select <type><%= phone.@ns:type %></type>
%>
</phoneTypes>
Console.WriteLine(phoneTypes)
End Sub
End Module
Per altre informazioni, vedere XML.
" output is necessary.)
Argomento | Descrizione |
---|---|
XML | Vengono descritte le funzionalità XML di Visual Basic su cui è possibile eseguire query e che consentono di includere XML come oggetti dati di prima classe nel codice Visual Basic. |
Query | Fornisce informazioni di riferimento sulle clausole di query disponibili in Visual Basic. |
LINQ ( queryLanguage-Integrated) | Include informazioni generali, linee guida di programmazione ed esempi per LINQ. |
LINQ to SQL | Include informazioni generali, indicazioni sulla programmazione ed esempi per LINQ to SQL. |
LINQ to Objects | Include informazioni generali, indicazioni sulla programmazione ed esempi per LINQ to Objects. |
LINQ to ADO.NET (pagina del portale) | Include collegamenti a informazioni generali, indicazioni sulla programmazione ed esempi per LINQ to ADO.NET. |
LINQ to XML | Include informazioni generali, indicazioni sulla programmazione ed esempi per LINQ to XML. |
Guide pratiche e argomenti dettagliati
Procedura: Interrogare un database
Come fare: Chiamare una procedura archiviata
Procedura: Modificare i dati in un database
Procedura: Combinare dati con operazioni di join
Procedura: Ordinare i risultati delle query
Procedura: Filtrare i risultati delle query
Come fare per contare, sommare o calcolare la media dei dati
Procedura: Trovare il valore minimo o massimo in un risultato della query
Capitoli di libri in evidenza
Capitolo 17: LINQ nella programmazione di Visual Basic 2008