Esecuzione di query sul servizio dati (WCF Data Services)
La libreria client di WCF Data Services consente di eseguire query su un servizio dati mediante i modelli di programmazione comuni di .NET Framework, compreso il linguaggio LINQ (Language Integrated Query). La libreria client traduce una query, definita nel client come un'istanza della classe DataServiceQuery, in un messaggio di richiesta HTTP GET. La libreria riceve il messaggio di risposta e lo converte in istanze delle classi del servizio dati client. Queste classi vengono rilevate dalla classe DataServiceContext a cui appartiene DataServiceQuery.
Query sul servizio dati
La classe generica DataServiceQuery rappresenta una query che restituisce una raccolta di zero o più istanze di tipi di entità. Una query sul servizio dati appartiene sempre a un contesto del servizio dati esistente. Il contesto gestisce l'URI del servizio e le informazioni sui metadati necessarie per comporre ed eseguire la query.
Quando si utilizza la finestra di dialogo Aggiungi riferimento al servizio per aggiungere un servizio dati a un'applicazione client basata su .NET Framework, viene creata una classe contenitore di entità che eredita dalla classe DataServiceContext. Tale classe include proprietà che restituiscono istanze della classe DataServiceQuery tipizzate. Esiste una proprietà per ogni set di entità esposto dal servizio dati. Tali proprietà semplificano la creazione di un'istanza di DataServiceQuery tipizzata.
Una query viene eseguita negli scenari seguenti:
Quando i risultati vengono enumerati in modo implicito, ad esempio:
Quando viene enumerata una proprietà della classe DataServiceContext che rappresenta un set di entità, ad esempio durante un ciclo foreach (C#) o For Each (Visual Basic).
Quando la query viene assegnata a una raccolta List.
Quando viene chiamato il metodo Execute o BeginExecute in modo esplicito.
Quando viene chiamato un operatore di esecuzione di query LINQ, ad esempio First o Single.
La query seguente, al termine dell'esecuzione, restituisce tutte le entità Customers
nel servizio dati Northwind:
' Define a new query for Customers.
Dim query As DataServiceQuery(Of Customer) = context.Customers
// Define a new query for Customers.
DataServiceQuery<Customer> query = context.Customers;
Per ulteriori informazioni, vedere Procedura: eseguire query sul servizio dati (WCF Data Services).
Il client WCF Data Services supporta le query per gli oggetti ad associazione tardiva, ad esempio quando si utilizza il tipo dinamico in C#. Tuttavia, per preservare le prestazioni, è necessario comporre sempre query fortemente tipizzate per il servizio dati. Il tipo Tuple e oggetti dinamici non sono supportati dal client.
Query LINQ
Poiché la classe DataServiceQuery implementa l'interfaccia IQueryable definita tramite LINQ, la libreria client di WCF Data Services è in grado di trasformare le query LINQ sui dati di set di entità in un URI che rappresenta un'espressione di query valutata in base a una risorsa del servizio dati. Nell'esempio seguente viene mostrata una query LINQ equivalente alla precedente classe DataServiceQuery che restituisce le entità Orders
con un costo di spedizione maggiore di 30 dollari e ordina i risultati in base al costo di spedizione:
Dim selectedOrders = From o In context.Orders _
Where (o.Freight > 30) _
Order By o.ShippedDate Descending _
Select o
var selectedOrders = from o in context.Orders
where o.Freight > 30
orderby o.ShippedDate descending
select o;
Questa query LINQ viene convertita nel seguente URI di query che viene eseguito sul servizio dati Guida rapida basato su Northwind:
https://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30
Nota: |
---|
La sintassi LINQ consente di esprimere un set di query più ampio di quello consentito dalla sintassi URI basata su REST (Representational State Transfer) utilizzata dai servizi dati. Quando non è possibile eseguire il mapping della query a un URI nel servizio dati di destinazione, viene generato un oggetto NotSupportedException. |
Per ulteriori informazioni, vedere Considerazioni su LINQ (WCF Data Services).
Aggiunta di opzioni di query
Le query del servizio dati supportano tutte le opzioni di query fornite da WCF Data Services . Il metodo AddQueryOption viene chiamato per aggiungere opzioni di query a un'istanza di DataServiceQuery. AddQueryOption restituisce una nuova istanza di DataServiceQuery equivalente alla query originale ma con il nuovo set di opzioni di query. La query seguente al termine dell'esecuzione restituisce oggetti Orders
filtrati in base al valore di Freight
e ordinati in ordine decrescente per OrderID
:
' Define a query for orders with a Freight value greater than 30
' and that is ordered by the ship date, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = context.Orders _
.AddQueryOption("$filter", "Freight gt 30") _
.AddQueryOption("$orderby", "OrderID desc")
// Define a query for orders with a Freight value greater than 30
// and that is ordered by the ship date, descending.
DataServiceQuery<Order> selectedOrders = context.Orders
.AddQueryOption("$filter", "Freight gt 30")
.AddQueryOption("$orderby", "OrderID desc");
È possibile utilizzare l'opzione di query $orderby per ordinare e filtrare una query in base a una singola proprietà, come nell'esempio seguente in cui gli oggetti Orders
restituiti vengono filtrati e ordinati in base al valore della proprietà Freight
:
' Create the DataServiceContext using the service URI.
Dim context = New NorthwindEntities(svcUri)
' Define a query for orders with a Freight value greater than 30
' that also orders the result by the Freight value, descending.
Dim selectedOrders As DataServiceQuery(Of Order) = _
context.Orders.AddQueryOption("$orderby", "Freight gt 30 desc")
Try
' Enumerate over the results of the query.
For Each order As Order In selectedOrders
Console.WriteLine("Order ID: {0} - Freight: {1}", _
order.OrderID, order.Freight)
Next
Catch ex As DataServiceQueryException
Throw New ApplicationException( _
"An error occurred during query execution.", ex)
End Try
// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri);
// Define a query for orders with a Freight value greater than 30
// that also orders the result by the Freight value, descending.
DataServiceQuery<Order> selectedOrders = context.Orders
.AddQueryOption("$orderby", "Freight gt 30 desc");
try
{
// Enumerate over the results of the query.
foreach (Order order in selectedOrders)
{
Console.WriteLine("Order ID: {0} - Freight: {1}",
order.OrderID, order.Freight);
}
}
catch (DataServiceQueryException ex)
{
throw new ApplicationException(
"An error occurred during query execution.", ex);
}
È possibile chiamare consecutivamente il metodo AddQueryOption per costruire espressioni di query complesse. Per ulteriori informazioni, vedere Procedura: aggiungere opzioni di query a una query del servizio dati (WCF Data Services).
Le opzioni di query costituiscono un altro modo per esprimere i componenti sintattici di una query LINQ. Per ulteriori informazioni, vedere Considerazioni su LINQ (WCF Data Services).
Nota: |
---|
L'opzione di query $select non può essere aggiunta a un URI di query tramite il metodo AddQueryOption. Si consiglia di utilizzare il metodo LINQ Select in modo che il client generi l'opzione di query $select nell'URI della richiesta. |
Esecuzione del client e del server
Il client esegue una query in due parti. Ogni qualvolta possibile, le espressioni di una query vengono prima valutate sul client e quindi viene generata una query basata sull'URI che viene inviata al servizio dati per la valutazione rispetto ai dati del servizio. Si consideri la query LINQ riportata di seguito:
Dim basePrice As Integer = 100
Dim discount As Decimal = Convert.ToDecimal(0.1)
' Define a query that returns products based on a
' calculation that is determined on the client.
Dim productsQuery = From p In context.Products
Where p.UnitPrice >
(basePrice - (basePrice * discount)) AndAlso
p.ProductName.Contains("bike")
Select p
int basePrice = 100;
decimal discount = .10M;
// Define a query that returns products based on a
// calculation that is determined on the client.
var productsQuery = from p in context.Products
where p.UnitPrice >
(basePrice - (basePrice * discount)) &&
p.ProductName.Contains("bike")
select p;
In questo esempio, l'espressione (basePrice – (basePrice * discount))
viene valutata sul client. Di conseguenza, l'URI di query effettivo https://localhost:12345/northwind.svc/Products()?$filter=(UnitPrice gt 90.00M) and substringof('bike',ProductName)
che viene inviato al servizio dati contiene il valore decimale già calcolato 90
nella clausola di filtro. Le altre parti dell'espressione dei filtri, compresa l'espressione della sottostringa, vengono valutate dal servizio dati. Le espressioni valutate sul client seguono la semantica di Common Language Runtime (CLR), mentre le espressioni inviate al servizio dati si basano sull'implementazione del servizio dati del protocollo OData . È anche necessario tenere presente scenari in cui questa valutazione separata può provocare risultati imprevisti, ad esempio quando il client e il servizio eseguono valutazioni basate sull'ora in fusi orari diversi.
Risposte alle query
Se eseguita, DataServiceQuery restituisce un oggetto IEnumerable del tipo di entità richiesto. È possibile eseguire il cast di questo risultato della query a un oggetto QueryOperationResponse, come nell'esempio seguente:
' Execute the query for all customers and get the response object.
Dim response As QueryOperationResponse(Of Customer) = _
CType(query.Execute(), QueryOperationResponse(Of Customer))
// Execute the query for all customers and get the response object.
QueryOperationResponse<Customer> response =
query.Execute() as QueryOperationResponse<Customer>;
Le istanze del tipo di entità che rappresentano entità nel servizio dati vengono create nel client tramite un processo denominato "materializzazione degli oggetti". Per ulteriori informazioni, vedere Materializzazione di oggetti (WCF Data Services). L'oggetto QueryOperationResponse implementa IEnumerable per fornire accesso ai risultati della query.
QueryOperationResponse dispone inoltre dei membri seguenti che consentono di accedere a informazioni aggiuntive sul risultato della query:
Error: ottiene un eventuale errore generato dall'operazione.
Headers: contiene la raccolta di intestazioni di risposta HTTP associate alla risposta alla query.
Query: ottiene l'istanza DataServiceQuery originale generata da QueryOperationResponse.
StatusCode: ottiene il codice di risposta HTTP per la risposta alla query.
TotalCount: ottiene il numero complessivo di entità del set di entità quando viene chiamato il metodo IncludeTotalCount su DataServiceQuery.
GetContinuation: restituisce un oggetto DataServiceQueryContinuation che contiene l'URI della pagina di risultati successiva.
Per impostazione predefinita, WCF Data Services restituisce solo i dati selezionati in modo esplicito dall'URI di query. Ciò consente di caricare in modo esplicito dati aggiuntivi dal servizio dati, quando necessario. Una richiesta viene inviata al servizio dati ogni volta che vengono caricati in modo esplicito dati dal servizio dati. I dati che possono essere caricati in modo esplicito comprendono entità correlate, dati di risposta di paging e flussi di dati binari.
Nota: |
---|
Poiché un servizio dati può restituire una risposta di paging, si consiglia di gestire una risposta del servizio dati sottoposta a paging tramite un modello di programmazione dell'applicazione. Per ulteriori informazioni, vedere Caricamento di contenuto posticipato (WCF Data Services). |
È inoltre possibile ridurre la quantità di dati restituiti da una query specificando che solo determinate proprietà di un'entità vengano restituite nella risposta. Per ulteriori informazioni, vedere Proiezioni di query (WCF Data Services).
Conteggio del numero complessivo di entità nel set
In alcuni scenari è utile conoscere il numero complessivo di entità contenute in un set di entità e non soltanto il numero restituito dalla query. Chiamare il metodo IncludeTotalCount su DataServiceQuery per richiedere che nel risultato della query venga incluso il conteggio totale delle entità presenti nel set. In questo caso la proprietà TotalCount dell'oggetto QueryOperationResponse restituito contiene il numero totale di entità nel set.
È anche possibile ottenere solo il conteggio totale delle entità nel set come valore Int32 o Int64 chiamando rispettivamente i metodi Count o LongCount. Quando vengono chiamati questi metodi, viene restituito solo il valore del conteggio senza QueryOperationResponse. Per ulteriori informazioni, vedere Procedura: determinare il numero di entità restituite da una query (WCF Data Services).
In questa sezione
Proiezioni di query (WCF Data Services)
Materializzazione di oggetti (WCF Data Services)
Considerazioni su LINQ (WCF Data Services)
Procedura: eseguire query sul servizio dati (WCF Data Services)
Procedura: aggiungere opzioni di query a una query del servizio dati (WCF Data Services)
Procedura: determinare il numero di entità restituite da una query (WCF Data Services)
Procedura: impostare le intestazioni nella richiesta del client (WCF Data Services)
Procedura: proiettare i risultati delle query (WCF Data Services)