Considerazioni su LINQ (WCF Data Services)
In questo argomento vengono fornite informazioni sulla modalità con cui le query LINQ vengono composte ed eseguite quando si utilizza il client WCF Data Services e sulle limitazioni dell'utilizzo di LINQ per eseguire una query su un servizio dati che implementa OData (Open Data Protocol) . Per ulteriori informazioni su lla composizione ed esecuzione di query per un servizio dati basato su OData , vedere Esecuzione di query sul servizio dati (WCF Data Services).
Composizione di query LINQ
LINQ consente di comporre query per una raccolta di oggetti che implementa IEnumerable. La finestra di dialogo Aggiungi riferimento al servizio in Visual Studio e lo strumento DataSvcUtil.exe sono utilizzati per generare la rappresentazione di un servizio OData come classe di contenitore di entità che eredita da DataServiceContext e gli oggetti che rappresentano le entità restituite nei feed. Questi strumenti generano anche le proprietà per la classe contenitore di entità delle raccolte esposte come feed dal servizio. Ognuna di queste proprietà della classe che incapsula il servizio dati restituisce un elemento DataServiceQuery. Dal momento che la classe DataServiceQuery implementa l'interfaccia IQueryable definita da LINQ, in WCF Data Services è possibile comporre una query LINQ per i feed esposti dal servizio dati che vengono convertiti dalla libreria client in un URI di richiesta query inviato al servizio dati in esecuzione.
Nota: |
---|
La sintassi LINQ consente di esprimere un set di query più ampio di quello consentito dalla sintassi URI utilizzata dai servizi dati OData . Quando non è possibile eseguire il mapping della query a un URI nel servizio dati di destinazione viene generata un'eccezione NotSupportedException. Per ulteriori informazioni, vedere Unsupported LINQ Methods in questo argomento. |
Nell'esempio seguente viene riportata una query LINQ che restituisce gli elementi Orders
con un costo di spedizione maggiore di 30 dollari e ordina i risultati in base alla data di spedizione, partendo da quella più recente:
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
Per informazioni generali su LINQ, vedere Language-Integrated Query (LINQ).
LINQ consente di comporre query tramite la sintassi di query dichiarativa specifica della lingua, mostrata nell'esempio precedente, e un set di metodi di query noti come operatori di query standard. Una query equivalente a quella dell'esempio precedente può essere composta solo tramite la sintassi basata sul metodo, come indicato nell'esempio seguente:
Dim selectedOrders = context.Orders _
.Where(Function(o) o.Freight.Value > 30) _
.OrderByDescending(Function(o) o.ShippedDate)
var selectedOrders = context.Orders
.Where(o => o.Freight > 30)
.OrderByDescending(o => o.ShippedDate);
Il client WCF Data Services è in grado di convertire entrambi tipi di query composte in un URI di query ed è possibile estendere una query LINQ aggiungendo i metodi di query a un'espressione di query. Quando si compongono query LINQ aggiungendo la sintassi del metodo a un'espressione di query o un elemento DataServiceQuery, le operazioni vengono aggiunte all'URI della query nell'ordine di chiamata dei metodi. Equivale alla chiamata del metodo AddQueryOption per aggiungere ogni opzione di query all'URI della query.
Esecuzione di query LINQ
Alcuni metodi di query LINQ, ad esempio First o Single, quando vengono aggiunti alla query ne causano l'esecuzione. Una query viene eseguita anche quando i risultati vengono enumerati in modo implicito, ad esempio durante un ciclo foreach o quando la query è assegnata a una raccolta List. Per ulteriori informazioni, vedere Esecuzione di query sul servizio dati (WCF Data Services).
Il client esegue una query LINQ in due parti. Ogni qualvolta possibile, le espressioni LINQ 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. Per ulteriori informazioni, vedere la sezione Client versus Server Execution in Esecuzione di query sul servizio dati (WCF Data Services).
Quando non è possibile convertire una query LINQ in un URI di query conforme a OData , viene generata un'eccezione quando viene tentata l'esecuzione. Per ulteriori informazioni, vedere Esecuzione di query sul servizio dati (WCF Data Services).
Esempi di query LINQ
Negli esempi delle sezioni seguenti vengono illustrati i tipi di query LINQ che possono essere eseguiti su un servizio OData .
Filtro
Negli esempi di query LINQ in questa sezione vengono filtrati i dati nel feed restituito dal servizio.
Negli esempi seguenti vengono illustrate query equivalenti che filtrano le entità Orders
restituite in modo che vengano restituiti solo gli ordini con un costo di spedizione maggiore di $30:
Uso della sintassi di query LINQ:
Dim filteredOrders = From o In context.Orders Where o.Freight.Value > 30 Select o
var filteredOrders = from o in context.Orders where o.Freight > 30 select o;
Uso dei metodi di query LINQ:
Dim filteredOrders = context.Orders.Where(Function(o) o.Freight.Value > 0)
var filteredOrders = context.Orders .Where(o => o.Freight > 30);
Opzione $filter della stringa di query:
' Define a query for orders with a Freight value greater than 30. Dim filteredOrders _ = context.Orders.AddQueryOption("$filter", "Freight gt 30M")
// Define a query for orders with a Freight value greater than 30. var filteredOrders = context.Orders.AddQueryOption("$filter", "Freight gt 30M");
Tutti gli esempi precedenti vengono convertiti nell'URI di query: https://localhost:12345/northwind.svc/Orders()?$filter=Freight gt 30M
.
Ordinamento
Negli esempi seguenti vengono illustrate query equivalenti che ordinano i dati restituiti in base al nome dell'azienda e al codice postale, in ordine decrescente:
Uso della sintassi di query LINQ:
Dim sortedCustomers = From c In context.Customers Order By c.CompanyName Ascending, c.PostalCode Descending Select c
var sortedCustomers = from c in context.Customers orderby c.CompanyName ascending, c.PostalCode descending select c;
Uso dei metodi di query LINQ:
Dim sortedCustomers = context.Customers.OrderBy(Function(c) c.CompanyName) _ .ThenByDescending(Function(c) c.PostalCode)
var sortedCustomers = context.Customers.OrderBy(c => c.CompanyName) .ThenByDescending(c => c.PostalCode);
Opzione $orderby della stringa di query:
Dim sortedCustomers = context.Customers _ .AddQueryOption("$orderby", "CompanyName, PostalCode desc")
var sortedCustomers = context.Customers .AddQueryOption("$orderby", "CompanyName, PostalCode desc");
Tutti gli esempi precedenti vengono convertiti nell'URI di query: https://localhost:12345/northwind.svc/Customers()?$orderby=CompanyName,PostalCode desc
.
Proiezione
Negli esempi seguenti vengono illustrate query equivalenti che ordinano i dati restituiti dal progetto nel tipo CustomerAddress
più ristretto:
Uso della sintassi di query LINQ:
Dim projectedQuery = From c In context.Customers Select New CustomerAddress With { .CustomerID = c.CustomerID, .Address = c.Address, .City = c.City, .Region = c.Region, .PostalCode = c.PostalCode, .Country = c.Country }
var projectedQuery = from c in context.Customers select new CustomerAddress { CustomerID = c.CustomerID, Address = c.Address, City = c.City, Region = c.Region, PostalCode = c.PostalCode, Country = c.Country };
Uso dei metodi di query LINQ:
Dim projectedQuery = context.Customers.Where(Function(c) c.Country = "Germany") _ .Select(Function(c) New CustomerAddress With { .CustomerID = c.CustomerID, .Address = c.Address, .City = c.City, .Region = c.Region, .PostalCode = c.PostalCode, .Country = c.Country })
var projectedQuery = context.Customers.Where(c => c.Country == "Germany") .Select(c => new CustomerAddress { CustomerID = c.CustomerID, Address = c.Address, City = c.City, Region = c.Region, PostalCode = c.PostalCode, Country = c.Country});
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. |
Entrambi gli esempi precedenti vengono convertiti nell'URI di query: "https://localhost:12345/northwind.svc/Customers()?$filter=Country eq 'GerGerm'&$select=CustomerID,Address,City,Region,PostalCode,Country"
.
Paging del client
Negli esempi seguenti vengono illustrate query equivalenti che richiedono una pagina delle entità ordinate che include 25 ordini, ignorando i primi 50 ordini:
Applicazione di metodi di query a una query LINQ:
Dim pagedOrders = (From o In context.Orders Order By o.OrderDate Descending Select o) _ .Skip(50).Take(25)
var pagedOrders = (from o in context.Orders orderby o.OrderDate descending select o).Skip(50).Take(25);
Opzioni $skip e $top della stringa di query dell'URI:
Dim pagedOrders = context.Orders _ .AddQueryOption("$orderby", "OrderDate desc") _ .AddQueryOption("$skip", 50) _ .AddQueryOption("$top", 25) _
var pagedOrders = context.Orders .AddQueryOption("$orderby", "OrderDate desc") .AddQueryOption("$skip", 50) .AddQueryOption("$top", 25);
Entrambi gli esempi precedenti vengono convertiti nell'URI di query: https://localhost:12345/northwind.svc/Orders()?$orderby=OrderDate desc&$skip=50&$top=25
.
Espansione
Quando si esegue una query su un servizio dati OData , è possibile richiedere che le entità relative all'entità di destinazione della query siano incluse nel feed restituito. Il metodo Expand viene chiamato su DataServiceQuery per il set di entità indirizzato dalla query LINQ, con il relativo nome del set di entità fornito come parametro path. Per ulteriori informazioni, vedere Caricamento di contenuto posticipato (WCF Data Services).
Negli esempi seguenti vengono mostrate modalità equivalenti per utilizzare il metodo Expand in una query:
Nella sintassi della query LINQ:
Dim ordersQuery = From o In context.Orders.Expand("Order_Details") Where o.CustomerID = "ALFKI" Select o
var ordersQuery = from o in context.Orders.Expand("Order_Details") where o.CustomerID == "ALFKI" select o;
Con i metodi di query LINQ:
Dim ordersQuery = context.Orders.Expand("Order_Details") _ .Where(Function(o) o.CustomerID = "ALFKI")
var ordersQuery = context.Orders.Expand("Order_Details") .Where(o => o.CustomerID == "ALFKI");
Entrambi gli esempi precedenti vengono convertiti nell'URI di query: https://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details
.
Metodi LINQ non supportati
Nella tabella seguente sono riportate le classi dei metodi LINQ non supportati che non possono essere incluse in una query eseguita su un servizio OData :
Tipo di operazione | Metodo non supportato |
---|---|
Operatori di impostazione |
Tutti gli operatori di impostazione non sono supportati con DataServiceQuery, compresi quelli indicati di seguito: |
Operatori di ordinamento |
Gli operatori di ordinamento seguenti che richiedono IComparer non sono supportati con DataServiceQuery: |
Operatori di proiezione e di filtro |
I seguenti operatori di proiezione e filtro che accettano un argomento posizionale non sono supportati con DataServiceQuery: |
Operatori di raggruppamento |
Tutti gli operatori di raggruppamento non sono supportati con DataServiceQuery, compresi quelli indicati di seguito: È necessario eseguire le operazioni di raggruppamento sul client. |
Operatori di aggregazione |
Tutti gli operatori di aggregazione non sono supportati con DataServiceQuery, compresi quelli indicati di seguito: Le operazioni di aggregazione devono essere eseguite sul client o devono essere incapsulate da un'operazione del servizio. |
Operatori di paging |
Gli operatori di paging seguenti non sono supportati con DataServiceQuery:
Nota:
Gli operatori di paging eseguiti in una sequenza vuota restituiscono null.
|
Altri operatori |
Gli operatori seguenti non sono supportati con DataServiceQuery: |
Funzioni di espressione non supportate
Le proprietà e i metodi Common Language Runtime (CLR) riportati di seguito sono supportati perché possono essere convertiti in un'espressione di query per l'inclusione nell'URI della richiesta a un servizio OData :
Membro String | Funzione OData supportata |
---|---|
string concat(string p0, string p1) |
|
bool substringof(string p0, string p1) |
|
bool endswith(string p0, string p1) |
|
int indexof(string p0, string p1) |
|
int length(string p0) |
|
string replace(string p0, string find, string replace) |
|
string substring(string p0, int pos) |
|
string substring(string p0, int pos, int length) |
|
string tolower(string p0) |
|
string toupper(string p0) |
|
string trim(string p0) |
Membro1 DateTime | Funzione OData supportata |
---|---|
int day(DateTime p0) |
|
int hour(DateTime p0) |
|
int minute(DateTime p0) |
|
int month(DateTime p0) |
|
int second(DateTime p0) |
|
int year(DateTime p0) |
1In Visual Basic sono supportate anche le proprietà equivalenti di data e ora di Microsoft.VisualBasic.DateAndTime, nonché il metodo DatePart.
Membro Math | Funzione OData supportata |
---|---|
decimal ceiling(decimal p0) |
|
double ceiling(double p0) |
|
decimal floor(decimal p0) |
|
double floor(double p0) |
|
decimal round(decimal p0) |
|
double round(double p0) |
Membro Expression | Funzione OData supportata |
---|---|
bool isof(type p0) |
È possibile che il client sia anche in grado di valutare funzioni CLR aggiuntive sul client. Viene generata un'eccezione NotSupportedException per qualsiasi espressione che non può essere valutata sul client e non può essere convertita in un URI della richiesta valido per la valutazione sul server.
Vedere anche
Concetti
Esecuzione di query sul servizio dati (WCF Data Services)
Proiezioni di query (WCF Data Services)
Materializzazione di oggetti (WCF Data Services)