Query su singola tabella (LINQ to DataSet)
Le query LINQ (Language Integrated Query) funzionano su origini dati che implementano l'interfaccia IEnumerable<T> o l'interfaccia IQueryable<T>. Poiché la classe DataTable non implementa nessuna di queste due interfacce, è necessario chiamare il metodo AsEnumerable se si desidera usare DataTable come origine nella clausola From
della query LINQ.
Nell'esempio seguente vengono ottenuti tutti gli ordini online della tabella SalesOrderHeader e l'output costituito da ID ordine, data dell'ordine e numero di ordine viene inviato alla console.
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable orders = ds.Tables["SalesOrderHeader"];
var query =
from order in orders.AsEnumerable()
where order.Field<bool>("OnlineOrderFlag") == true
select new
{
SalesOrderID = order.Field<int>("SalesOrderID"),
OrderDate = order.Field<DateTime>("OrderDate"),
SalesOrderNumber = order.Field<string>("SalesOrderNumber")
};
foreach (var onlineOrder in query)
{
Console.WriteLine("Order ID: {0} Order date: {1:d} Order number: {2}",
onlineOrder.SalesOrderID,
onlineOrder.OrderDate,
onlineOrder.SalesOrderNumber);
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim orders As DataTable = ds.Tables("SalesOrderHeader")
Dim query = _
From order In orders.AsEnumerable() _
Where order.Field(Of Boolean)("OnlineOrderFlag") = True _
Select New With { _
.SalesOrderID = order.Field(Of Integer)("SalesOrderID"), _
.OrderDate = order.Field(Of DateTime)("OrderDate"), _
.SalesOrderNumber = order.Field(Of String)("SalesOrderNumber") _
}
For Each onlineOrder In query
Console.Write("Order ID: " & onlineOrder.SalesOrderID)
Console.Write(" Order date: " & onlineOrder.OrderDate)
Console.WriteLine(" Order number: " & onlineOrder.SalesOrderNumber)
Next
La query con variabili locali viene inizializzata con un'espressione di query, che opera su una o più fonti di informazione applicando uno o più operatori di query di tipo standard o, nel caso di LINQ to DataSet, specifici della classe DataSet. Nell'espressione di query dell'esempio precedente vengono usati due operatori di query standard: Where
e Select
.
La clausola Where
filtra la sequenza in base a una condizione, in questo caso che OnlineOrderFlag
sia impostato su true
. L'operatore Select
alloca e restituisce un oggetto enumerabile che acquisisce gli argomenti passati all'operatore. Nell'esempio precedente viene creato un tipo anonimo con tre proprietà: SalesOrderID
, OrderDate
e SalesOrderNumber
. I valori di queste tre proprietà vengono impostati sui valori delle colonne SalesOrderID
, OrderDate
e SalesOrderNumber
della tabella SalesOrderHeader
.
Il ciclo foreach
enumera quindi gli oggetti enumerabili restituiti da Select
e produce i risultati della query. Poiché la query è un tipo Enumerable, che implementa IEnumerable<T>, la valutazione della query viene posticipata finché non viene eseguita un'iterazione della variabile di query in un ciclo foreach
. La valutazione posticipata della query consente di mantenere le query come valori che è possibile valutare più volte, ogni volta con un risultato potenzialmente diverso.
Il metodo Field fornisce l'accesso ai valori di colonna di un oggetto DataRow e SetField (non illustrato nell'esempio precedente) imposta i valori di colonna in DataRow. Poiché i metodi Field e SetField gestiscono tipi valori nullable, non è necessario verificare in modo esplicito la presenza di valori Null. Entrambi metodi sono inoltre generici, quindi non è necessario eseguire i cast del tipo restituito. È possibile usare la funzione di accesso della colonna preesistente in DataRow (ad esempio, o["OrderDate"]
), ma in questo caso è necessario eseguire il cast dell'oggetto restituito nel tipo appropriato. Se la colonna è un tipo valore nullable, è necessario verificare se il valore è Null usando il metodo IsNull. Per altre informazioni, vedere Metodi Generic Field e SetField.
Si noti che il tipo di dati specificato nel parametro T
generico del metodo Field e del metodo SetField deve corrispondere al tipo del valore sottostante; in caso contrario, verrà generata un'eccezione InvalidCastException. Il nome di colonna specificato deve inoltre corrispondere al nome di una colonna presente in DataSet; in caso contrario, verrà generata un'eccezione ArgumentException. In entrambi casi, l'eccezione viene generata in fase di esecuzione durante l'enumerazione dei dati quando viene eseguita la query.