Considerazioni su LINQ (WCF Data Services)LINQ Considerations (WCF Data Services)

In questo argomento vengono fornite informazioni sulla modalità con cui le query LINQ vengono composte ed eseguite quando si usa il client WCF Data ServicesWCF Data Services e sulle limitazioni dell'utilizzo di LINQ per eseguire una query su un servizio dati che implementa Protocollo OData (Open Data)Open Data Protocol (OData).This topic provides information about the way in which LINQ queries are composed and executed when you are using the WCF Data ServicesWCF Data Services client and limitations of using LINQ to query a data service that implements the Protocollo OData (Open Data)Open Data Protocol (OData). Per altre informazioni suFor more information aboutla composizione e l'esecuzione di query su un ODataOData-basato su servizio dati, vedere l'esecuzione di query del servizio dati. composing and executing queries against an ODataOData-based data service, see Querying the Data Service.

Composizione di query LINQComposing LINQ Queries

LINQ consente di comporre query per una raccolta di oggetti che implementa IEnumerable<T>.LINQ enables you to compose queries against a collection of objects that implements IEnumerable<T>. Entrambi i Aggiungi riferimento al servizio nella finestra di dialogo Visual Studio e lo strumento DataSvcUtil.exe sono usati per generare una rappresentazione di un ODataOData servizio come classe contenitore di entità che eredita da DataServiceContext, così come oggetti che rappresentano le entità restituite nei feed.Both the Add Service Reference dialog box in Visual Studio and the DataSvcUtil.exe tool are used to generate a representation of an ODataOData service as an entity container class that inherits from DataServiceContext, as well as objects that represent the entities returned in feeds. Questi strumenti generano anche le proprietà per la classe contenitore di entità delle raccolte esposte come feed dal servizio.These tools also generate properties on the entity container class for the collections that are exposed as feeds by the service. Ognuna di queste proprietà della classe che incapsula il servizio dati restituisce un elemento DataServiceQuery<TElement>.Each of these properties of the class that encapsulates the data service return a DataServiceQuery<TElement>. Dal momento che la classe DataServiceQuery<TElement> implementa l'interfaccia IQueryable<T> definita da LINQ, è 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.Because the DataServiceQuery<TElement> class implements the IQueryable<T> interface defined by LINQ, you can compose a LINQ query against feeds exposed by the data service, which are translated by the client library into a query request URI that is sent to the data service on execution.

Importante

La sintassi LINQ consente di esprimere un set di query più ampio di quello consentito dalla sintassi URI usata dai servizi dati ODataOData.The set of queries expressible in the LINQ syntax is broader than those enabled in the URI syntax that is used by ODataOData data services. Quando non è possibile eseguire il mapping della query a un URI nel servizio dati di destinazione, viene generato un oggetto NotSupportedException.A NotSupportedException is raised when the query cannot be mapped to a URI in the target data service. Per altre informazioni, vedereFor more information, seeil metodi LINQ non supportati in questo argomento. the Unsupported LINQ Methods in this topic.

Nell'esempio seguente viene riportata una query LINQ che restituisce 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:The following example is a LINQ query that returns Orders that have a freight cost of more than $30 and sorts the results by the shipping date, starting with the latest ship date:

var selectedOrders = from o in context.Orders
                     where o.Freight > 30
                     orderby o.ShippedDate descending 
                     select o;
Dim selectedOrders = From o In context.Orders _
        Where (o.Freight > 30) _
        Order By o.ShippedDate Descending _
        Select o

Questa query LINQ viene convertita nella query seguente URI che viene eseguita su basato su Northwind delle Guide rapide servizio dati:This LINQ query is translated into the following query URI that is executed against the Northwind-based quickstart data service:

http://localhost:12345/Northwind.svc/Orders?Orderby=ShippedDate&?filter=Freight gt 30  

Per ulteriori informazioni generali su LINQ, vedere LINQ (Language-Integrated Query).For more general information about LINQ, see LINQ (Language-Integrated Query).

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.LINQ enables you to compose queries by using both the language-specific declarative query syntax, shown in the previous example, as well as a set of query methods known as standard query operators. Una query equivalente a quella dell'esempio precedente può essere composta solo tramite la sintassi basata sul metodo, come indicato nell'esempio seguente:An equivalent query to the previous example can be composed by using only the method-based syntax, as shown the following example:

var selectedOrders = context.Orders
                    .Where(o => o.Freight > 30)
                    .OrderByDescending(o => o.ShippedDate);
Dim selectedOrders = context.Orders _
                     .Where(Function(o) o.Freight.Value > 30) _
                     .OrderByDescending(Function(o) o.ShippedDate)

Il client WCF Data ServicesWCF 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.The WCF Data ServicesWCF Data Services client is able to translate both kinds of composed queries into a query URI, and you can extend a LINQ query by appending query methods to a query expression. Quando si compongono query LINQ aggiungendo la sintassi del metodo a un'espressione di query o un elemento DataServiceQuery<TElement>, le operazioni vengono aggiunte all'URI della query nell'ordine di chiamata dei metodi.When you compose LINQ queries by appending method syntax to a query expression or a DataServiceQuery<TElement>, the operations are added to the query URI in the order in which methods are called. Equivale alla chiamata del metodo AddQueryOption per aggiungere ogni opzione di query all'URI della query.This is equivalent to calling the AddQueryOption method to add each query option to the query URI.

Esecuzione di query LINQExecuting LINQ Queries

Alcuni metodi di query LINQ, ad esempio First<TSource>(IEnumerable<TSource>) o Single<TSource>(IEnumerable<TSource>), quando vengono aggiunti alla query ne causano l'esecuzione.Certain LINQ query methods, such as First<TSource>(IEnumerable<TSource>) or Single<TSource>(IEnumerable<TSource>), when appended to the query, cause the query to be executed. 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.A query is also executed when results are enumerated implicitly, such as during a foreach loop or when the query is assigned to a List collection. Per ulteriori informazioni, vedere l'esecuzione di query del servizio dati.For more information, see Querying the Data Service.

Il client esegue una query LINQ in due parti.The client executes a LINQ query in two parts. 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.Whenever possible, LINQ expressions in a query are first evaluated on the client, and then a URI-based query is generated and sent to the data service for evaluation against data in the service. Per ulteriori informazioni, vedere la sezione Client e Server esecuzione in l'esecuzione di query del servizio dati.For more information, see the section Client versus Server Execution in Querying the Data Service.

Quando non è possibile convertire una query LINQ in un URI di query conforme a ODataOData, viene generata un'eccezione quando viene tentata l'esecuzione.When a LINQ query cannot be translated in an ODataOData-compliant query URI, an exception is raised when execution is attempted. Per ulteriori informazioni, vedere l'esecuzione di query del servizio dati.For more information, see Querying the Data Service.

Esempi di query LINQLINQ Query Examples

Negli esempi delle sezioni seguenti vengono illustrati i tipi di query LINQ che possono essere eseguiti su un servizio ODataOData.The examples in the following sections demonstrate the kinds of LINQ queries that can be executed against an ODataOData service.

FiltroFiltering

Negli esempi di query LINQ in questa sezione vengono filtrati i dati nel feed restituito dal servizio.The LINQ query examples in this section filter data in the feed returned by the service.

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:The following examples are equivalent queries that filter the returned Orders entities so that only orders with a freight cost greater than $30 are returned:

  • Utilizzo della sintassi di query LINQ:Using LINQ query syntax:
var filteredOrders = from o in context.Orders
                        where o.Freight > 30
                        select o;
Dim filteredOrders = From o In context.Orders
                        Where o.Freight.Value > 30
                        Select o
  • Utilizzo dei metodi di query LINQ:Using LINQ query methods:
var filteredOrders = context.Orders
    .Where(o => o.Freight > 30);
Dim filteredOrders = context.Orders.Where(Function(o) o.Freight.Value > 0)
  • Opzione $filter della stringa di query:The URI query string $filter option:
// Define a query for orders with a Freight value greater than 30.
var filteredOrders
    = context.Orders.AddQueryOption("$filter", "Freight gt 30M");
' Define a query for orders with a Freight value greater than 30.
Dim filteredOrders _
            = context.Orders.AddQueryOption("$filter", "Freight gt 30M")

Tutti gli esempi precedenti vengono convertiti nell'URI di query: http://localhost:12345/northwind.svc/Orders()?$filter=Freight gt 30M.All of the previous examples are translated to the query URI: http://localhost:12345/northwind.svc/Orders()?$filter=Freight gt 30M.

OrdinamentoSorting

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:The following examples show equivalent queries that sort returned data both by the company name and by postal code, descending:

  • Utilizzo della sintassi di query LINQ:Using LINQ query syntax:
var sortedCustomers = from c in context.Customers
                     orderby c.CompanyName ascending, 
                     c.PostalCode descending
                     select c;
Dim sortedCustomers = From c In context.Customers
                             Order By c.CompanyName Ascending,
                             c.PostalCode Descending
                             Select c
  • Utilizzo dei metodi di query LINQ:Using LINQ query methods:
var sortedCustomers = context.Customers.OrderBy(c => c.CompanyName)
    .ThenByDescending(c => c.PostalCode);
Dim sortedCustomers = context.Customers.OrderBy(Function(c) c.CompanyName) _
.ThenByDescending(Function(c) c.PostalCode)
  • Opzione $orderby della stringa di query:URI query string $orderby option):
var sortedCustomers = context.Customers
    .AddQueryOption("$orderby", "CompanyName, PostalCode desc");
Dim sortedCustomers = context.Customers _
                      .AddQueryOption("$orderby", "CompanyName, PostalCode desc")

Tutti gli esempi precedenti vengono convertiti nell'URI di query: http://localhost:12345/northwind.svc/Customers()?$orderby=CompanyName,PostalCode desc.All of the previous examples are translated to the query URI: http://localhost:12345/northwind.svc/Customers()?$orderby=CompanyName,PostalCode desc.

ProiezioneProjection

Negli esempi seguenti vengono illustrate query equivalenti che ordinano i dati restituiti dal progetto nel tipo CustomerAddress più ristretto:The following examples show equivalent queries that project returned data into the narrower CustomerAddress type:

  • Utilizzo della sintassi di query LINQ:Using LINQ query syntax:
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
            };
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
                    }
  • Utilizzo dei metodi di query LINQ:Using LINQ query methods:
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});                   
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
            })

Nota

L'opzione di query $select non può essere aggiunta a un URI di query tramite il metodo AddQueryOption.The $select query option cannot be added to a query URI by using the AddQueryOption method. Si consiglia di usare il metodo LINQ Select in modo che il client generi l'opzione di query $select nell'URI della richiesta.We recommend that you use the LINQ Select method to have the client generate the $select query option in the request URI.

Entrambi gli esempi precedenti vengono convertiti nell'URI di query: "http://localhost:12345/northwind.svc/Customers()?$filter=Country eq 'GerGerm'&$select=CustomerID,Address,City,Region,PostalCode,Country".Both of the previous examples are translated to the query URI: "http://localhost:12345/northwind.svc/Customers()?$filter=Country eq 'GerGerm'&$select=CustomerID,Address,City,Region,PostalCode,Country".

Paging del clientClient Paging

Negli esempi seguenti vengono illustrate query equivalenti che richiedono una pagina delle entità ordinate che include 25 ordini, ignorando i primi 50 ordini:The following examples show equivalent queries that request a page of sorted order entities that includes 25 orders, skipping the first 50 orders:

  • Applicazione di metodi di query a una query LINQ:Applying query methods to a LINQ query:
var pagedOrders = (from o in context.Orders
                      orderby o.OrderDate descending
                     select o).Skip(50).Take(25);
Dim pagedOrders = (From o In context.Orders
                   Order By o.OrderDate Descending
                   Select o) _
               .Skip(50).Take(25)
  • Opzioni $skip e $top della stringa di query dell'URI:URI query string $skip and $top options):
var pagedOrders = context.Orders
    .AddQueryOption("$orderby", "OrderDate desc")
    .AddQueryOption("$skip", 50)
    .AddQueryOption("$top", 25);
Dim pagedOrders = context.Orders _
                  .AddQueryOption("$orderby", "OrderDate desc") _
                  .AddQueryOption("$skip", 50) _
                  .AddQueryOption("$top", 25) _

Entrambi gli esempi precedenti vengono convertiti nell'URI di query: http://localhost:12345/northwind.svc/Orders()?$orderby=OrderDate desc&$skip=50&$top=25.Both of the previous examples are translated to the query URI: http://localhost:12345/northwind.svc/Orders()?$orderby=OrderDate desc&$skip=50&$top=25.

EspandiExpand

Quando si esegue una query su un servizio dati ODataOData, è possibile richiedere che le entità relative all'entità di destinazione della query siano incluse nel feed restituito.When you query an ODataOData data service, you can request that entities related to the entity targeted by the query be included the returned feed. Il metodo Expand viene chiamato su DataServiceQuery<TElement> per il set di entità indirizzato dalla query LINQ, con il relativo nome del set di entità fornito come parametro path.The Expand method is called on the DataServiceQuery<TElement> for the entity set targeted by the LINQ query, with the related entity set name supplied as the path parameter. Per ulteriori informazioni, vedere durante il caricamento di contenuto posticipato.For more information, see Loading Deferred Content.

Negli esempi seguenti vengono mostrate modalità equivalenti per usare il metodo Expand in una query:The following examples show equivalent ways to use the Expand method in a query:

  • Nella sintassi della query LINQ:In LINQ query syntax:
var ordersQuery = from o in context.Orders.Expand("Order_Details")
                     where o.CustomerID == "ALFKI"
                     select o;
Dim ordersQuery = From o In context.Orders.Expand("Order_Details")
                     Where o.CustomerID = "ALFKI"
                     Select o
  • Con i metodi di query LINQ:With LINQ query methods:
var ordersQuery = context.Orders.Expand("Order_Details")
                  .Where(o => o.CustomerID == "ALFKI");
Dim ordersQuery = context.Orders.Expand("Order_Details") _
                          .Where(Function(o) o.CustomerID = "ALFKI")

Entrambi gli esempi precedenti vengono convertiti nell'URI di query: http://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details.Both of the previous examples are translated to the query URI: http://localhost:12345/northwind.svc/Orders()?$filter=CustomerID eq 'ALFKI'&$expand=Order_Details.

Metodi LINQ non supportatiUnsupported LINQ Methods

Nella tabella seguente sono riportate le classi dei metodi LINQ non supportati che non possono essere incluse in una query eseguita su un servizio ODataOData:The following table contains the classes of LINQ methods are not supported and cannot be included in a query executed against an ODataOData service:

Tipo di operazioneOperation Type Metodo non supportatoUnsupported Method
Operatori SetSet operators Tutti gli operatori Set non sono supportati con DataServiceQuery<TElement>, compresi quelli indicati di seguito:All set operators are unsupported against a DataServiceQuery<TElement>, which included the following:

- All
- Any
- Concat
- DefaultIfEmpty
- Distinct
- Except
- Intersect
- Union
- Zip
Operatori di ordinamentoOrdering operators Gli operatori di ordinamento seguenti che richiedono IComparer<T> non sono supportati con DataServiceQuery<TElement>:The following ordering operators that require IComparer<T> are unsupported against a DataServiceQuery<TElement>:

- OrderBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>, IComparer<TKey>)
- OrderByDescending<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>, IComparer<TKey>)
- ThenBy<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>, IComparer<TKey>)
- ThenByDescending<TSource,TKey>(IOrderedEnumerable<TSource>, Func<TSource,TKey>, IComparer<TKey>)
Operatori di proiezione e di filtroProjection and filtering operators I seguenti operatori di proiezione e filtro che accettano un argomento posizionale non sono supportati con DataServiceQuery<TElement>:The following projection and filtering operators that accept a positional argument are unsupported against a DataServiceQuery<TElement>:

- Join<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>, IEqualityComparer<TKey>)
- Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,Int32,TResult>)
- SelectMany<TSource,TResult>(IEnumerable<TSource>, Func<TSource,IEnumerable<TResult>>)
- SelectMany<TSource,TResult>(IEnumerable<TSource>, Func<TSource,Int32,IEnumerable<TResult>>)
- SelectMany<TSource,TCollection,TResult>(IEnumerable<TSource>, Func<TSource,IEnumerable<TCollection>>, Func<TSource,TCollection,TResult>)
- SelectMany<TSource,TCollection,TResult>(IEnumerable<TSource>, Func<TSource,Int32,IEnumerable<TCollection>>, Func<TSource,TCollection,TResult>)
- Where<TSource>(IEnumerable<TSource>, Func<TSource,Int32,Boolean>)
Operatori di raggruppamentoGrouping operators Tutti gli operatori di raggruppamento non sono supportati con DataServiceQuery<TElement>, compresi quelli indicati di seguito:All grouping operators are unsupported against a DataServiceQuery<TElement>, including the following:

- GroupBy
- GroupJoin

È necessario eseguire le operazioni di raggruppamento sul client.Grouping operations must be performed on the client.
Operatori di aggregazioneAggregate operators Tutti gli operatori di aggregazione non sono supportati con DataServiceQuery<TElement>, compresi quelli indicati di seguito:All aggregate operations are unsupported against a DataServiceQuery<TElement>, including the following:

- Aggregate
- Average
- Count
- LongCount
- Max
- Min
- Sum

Le operazioni di aggregazione devono essere eseguite sul client o devono essere incapsulate da un'operazione del servizio.Aggregate operations must either be performed on the client or be encapsulated by a service operation.
Operatori di pagingPaging operators Gli operatori di paging seguenti non sono supportati con DataServiceQuery<TElement>:The following paging operators are not supported against a DataServiceQuery<TElement>:

- ElementAt
- Last
- LastOrDefault
- SkipWhile
- TakeWhileNota: gli operatori di Paging che vengono eseguiti in una sequenza vuota restituiscono null.- TakeWhile Note: Paging operators that are executed on an empty sequence return null.
Altri operatoriOther operators Gli operatori seguenti non sono supportati con DataServiceQuery<TElement>:The following other operators are not supported against a DataServiceQuery<TElement>:

1. Empty1. Empty
2. Range2. Range
3. Repeat3. Repeat
4. ToDictionary4. ToDictionary
5. ToLookup5. ToLookup

Funzioni di espressione non supportateSupported Expression Functions

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 ODataOData:The following common-language runtime (CLR) methods and properties are supported because they can be translated in a query expression for inclusion in the request URI to an ODataOData service:

Membro StringString Member Funzione ODataOData supportataSupported ODataOData Function
Concat(String, String) string concat(string p0, string p1)
Contains(String) bool substringof(string p0, string p1)
EndsWith(String) bool endswith(string p0, string p1)
IndexOf(String, Int32) int indexof(string p0, string p1)
Length int length(string p0)
Replace(String, String) string replace(string p0, string find, string replace)
Substring(Int32) string substring(string p0, int pos)
Substring(Int32, Int32) string substring(string p0, int pos, int length)
ToLower() string tolower(string p0)
ToUpper() string toupper(string p0)
Trim() string trim(string p0)
DateTimeMembro1DateTime Member1 Funzione ODataOData supportataSupported ODataOData Function
Day int day(DateTime p0)
Hour int hour(DateTime p0)
Minute int minute(DateTime p0)
Month int month(DateTime p0)
Second int second(DateTime p0)
Year int year(DateTime p0)

1l'equivalente proprietà data e ora di Microsoft.VisualBasic.DateAndTime, nonché il DatePart sono supportate anche metodo in Visual Basic.1The equivalent date and time properties of Microsoft.VisualBasic.DateAndTime, as well as the DatePart method in Visual Basic are also supported.

Membro MathMath Member Funzione ODataOData supportataSupported ODataOData Function
Ceiling(Decimal) decimal ceiling(decimal p0)
Ceiling(Double) double ceiling(double p0)
Floor(Decimal) decimal floor(decimal p0)
Floor(Double) double floor(double p0)
Round(Decimal) decimal round(decimal p0)
Round(Double) double round(double p0)
Membro ExpressionExpression Member Funzione ODataOData supportataSupported ODataOData Function
TypeIs(Expression, Type) bool isof(type p0)

È possibile che il client sia anche in grado di valutare funzioni CLR aggiuntive sul client.The client may also be able to evaluate additional CLR functions on the 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.A NotSupportedException is raised for any expression that cannot be evaluated on the client and cannot be translated into a valid request URI for evaluation on the server.

Vedere ancheSee Also

Esecuzione di query sul servizio datiQuerying the Data Service
Proiezioni di queryQuery Projections
Materializzazione di oggettiObject Materialization
OData: Convenzioni URIOData: URI Conventions