Partager via


Interrogation du service de données (WCF Data Services)

La bibliothèque cliente Services de données WCF vous permet d'exécuter des requêtes sur un service de données à l'aide de modèles de programmation .NET Framework familiers, notamment LINQ (Language Integrated Query). La bibliothèque cliente traduit une requête, définie sur le client comme une instance de la classe DataServiceQuery<TElement>, en un message de demande HTTP GET. La bibliothèque reçoit le message de réponse et le traduit en instances des classes de service de données client. Ces classes sont suivies par DataServiceContext auquel DataServiceQuery<TElement> appartient.

Requêtes du service de données

La classe générique DataServiceQuery<TElement> représente une requête qui retourne une collection de zéro, une ou plusieurs instances de type d'entité. Une requête du service de données appartient toujours à un contexte du service de données existant. Ce contexte conserve les informations relatives à l'URI de service et aux métadonnées qui sont requises pour composer et exécuter la requête.

Lorsque vous utilisez la boîte de dialogue Ajouter une référence de service pour ajouter un service de données à une application cliente basée sur .NET Framework, une classe de conteneur d'entités qui hérite de la classe DataServiceContext est créée. Cette classe inclut des propriétés qui retournent des instances DataServiceQuery<TElement> typées. Il y a une propriété pour chaque jeu d'entités exposé par le service de données. Ces propriétés simplifient la création d'une instance d'un DataServiceQuery<TElement> typé.

Une requête est exécutée dans les scénarios suivants :

  • Lorsque les résultats sont énumérés implicitement, tel que :

    • Lorsqu'une propriété sur DataServiceContext qui représente un jeu d'entités est énumérée, comme pendant une boucle foreach (C#) ou For Each (Visual Basic).

    • Lorsque la requête est assignée à une collection List.

  • Lorsque la méthode Execute ou BeginExecute est explicitement appelée.

  • Lorsqu'un opérateur d'exécution de requête LINQ, tel que First ou Single est appelé.

La requête suivante, lorsqu'elle est exécutée, retourne toutes les entités Customers dans le service de données 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;

Pour plus d'informations, consultez Procédure : exécuter des requêtes de service des données (WCF Data Services).

Le client Services de données WCF prend en charge les requêtes d'objets à liaison tardive, comme lorsque vous utilisez le type dynamic en C#. Toutefois, pour de bonnes performances, vous devriez toujours composer des requêtes fortement typées sur le service de données. La type Tuple et les objets dynamiques ne sont pas pris en charge par le client.

Requêtes LINQ

Étant donné que la classe DataServiceQuery<TElement> implémente l'interface IQueryable<T> définie par LINQ, la bibliothèque cliente Services de données WCF est en mesure de transformer des requêtes LINQ sur des données de jeu d'entités en un URI qui représente une expression de requête évalué par rapport à une ressource du service de données. L'exemple suivant est une requête LINQ équivalente à l'instance DataServiceQuery<TElement> précédente qui retourne des Orders ayant un coût de fret supérieur à $30 et classe les résultats par coût de fret :

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;

Cette requête LINQ est traduite par l'URI de requête suivant exécuté sur le service de données démarrage rapide basé sur Northwind :

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

Notes

L'ensemble de requêtes pouvant être exprimées dans la syntaxe LINQ est plus étendu que dans la syntaxe d'URI REST (Representational State Transfer) utilisée par les services de données.NotSupportedException est levée lorsque la requête ne peut pas être mappée à un URI dans le service de données cible.

Pour plus d'informations, consultez Considérations sur LINQ (WCF Data Services).

Ajout d'options de requête

Les requêtes du service de données prennent en charge toutes les options de requête fournies par Services de données WCF. Vous appelez la méthode AddQueryOption pour ajouter les options de requête à une instance DataServiceQuery<TElement>. AddQueryOption retourne une nouvelle instance DataServiceQuery<TElement> qui est équivalente à la requête d'origine mais avec le nouveau jeu d'options de requête. La requête suivante, en cas d'exécution, retourne les Orders qui sont filtrées par la valeur Freight et classées par OrderID, dans l'ordre descendant :

' 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");

Vous pouvez utiliser l'option de requête $orderby pour organiser et filtrer une requête en fonction d'une seule propriété, comme dans l'exemple suivant qui filtre et organise les objets Orders retournés en fonction de la valeur de la propriété 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);
}

Vous pouvez appeler consécutivement la méthode AddQueryOption pour construire des expressions de requête complexes. Pour plus d'informations, consultez Procédure : ajouter des options de requête à une requête de service des données (WCF Data Services).

Les options de requête fournissent une autre méthode pour exprimer les composants syntactiques d'une requête LINQ. Pour plus d'informations, consultez Considérations sur LINQ (WCF Data Services).

Notes

L'option de requête $select ne peut pas être ajoutée à un URI de requête à l'aide de la méthode AddQueryOption(String, Object).Nous vous recommandons d'utiliser la méthode LINQ Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>) pour que le client génère l'option de requête $select dans l'URI de requête.

Exécution du client et exécution du serveur

Le client exécute une requête en deux parties. Lorsque cela est possible, les expressions dans une requête sont d'abord évaluées sur le client, puis une requête basée sur l'URI est générée et envoyée au service de données pour être évaluée par rapport aux données dans le service. Prenons la requête LINQ suivante :

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;

Dans cet exemple, l'expression (basePrice – (basePrice * discount)) est évaluée sur le client. À cause de cela, l'URI de requête réel https://localhost:12345/northwind.svc/Products()?$filter=(UnitPrice gt 90.00M) and substringof('bike',ProductName) transmis au service de données contient la valeur décimale 90 déjà calculée dans la clause de filtre. Les autres parties de l'expression de filtrage, y compris l'expression de la sous-chaîne, sont évaluées par le service de données. Les expressions qui sont évaluées sur le client suivent la sémantique CLR (Common Language Runtime), tandis que les expressions transmises au service de données reposent sur l'implémentation du protocole OData dans le service de données. Vous devriez également tenir compte des scénarios où cette évaluation séparée peut entraîner des résultats inattendus, comme quand le client et le service exécutent des évaluations basées sur le temps dans différents fuseaux horaires.

Réponses aux requêtes

En cas d'exécution, DataServiceQuery<TElement> retourne un IEnumerable<T> du type d'entité demandé. Ce résultat de requête peut être converti en un objet QueryOperationResponse<T>, comme dans l'exemple suivant :

' 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>;

Les instances de type d'entité qui représentent des entités dans le service de données sont créées sur le client par le biais d'un processus appelé matérialisation d'objets. Pour plus d'informations, consultez Matérialisation d'objets (WCF Data Services). L'objet QueryOperationResponse<T> implémente IEnumerable<T> pour fournir un accès aux résultats de la requête.

QueryOperationResponse<T> a également les membres suivants qui vous permettent d'accéder à des informations supplémentaires sur un résultat de requête :

Par défaut, Services de données WCF retourne seulement les données sélectionnées explicitement par l'URI de requête. Cela vous permet de charger explicitement des données supplémentaires à partir du service de données lorsque cela est nécessaire. Une demande est envoyée au service de données chaque fois vous chargez explicitement des données à partir du service de données. Les données qui peuvent être chargées explicitement incluent des entités associées, des données de réponse paginées et des flux de données binaires.

Notes

Étant donné qu'un service de données peut retourner une réponse paginée, nous recommandons que votre application utilise le modèle de programmation pour gérer une réponse du service de données paginée.Pour plus d'informations, consultez Chargement de contenu différé (WCF Data Services).

La quantité de données retournée par une requête peut également être réduite en spécifiant que seules certaines propriétés d'une entité doivent être retournées dans la réponse. Pour plus d'informations, consultez Projections de requête (WCF Data Services).

Obtenir un décompte du nombre total d'entités d'un jeu

Dans certains scénarios, il est utile de connaître le nombre total d'entités d'un jeu d'entités et pas simplement le nombre retourné par la requête. Appelez la méthode IncludeTotalCount sur l'instance DataServiceQuery<TElement> pour demander que le nombre total d'entités du jeu soit inclus dans le résultat de la requête. Dans ce cas, la propriété TotalCount du QueryOperationResponse<T> retourné renvoie le nombre total d'entités du jeu.

Vous pouvez également obtenir uniquement le nombre total d'entités du jeu comme un Int32 ou comme une valeur Int64 en appelant les méthodes Count ou LongCount respectivement. Lorsque ces méthodes sont appelées, le QueryOperationResponse<T> n'est pas retourné ; seule la valeur du compteur est retournée. Pour plus d'informations, consultez Procédure : déterminer le nombre d'entités retournées par une requête WCF Data Services.

Dans cette section

Projections de requête (WCF Data Services)

Matérialisation d'objets (WCF Data Services)

Considérations sur LINQ (WCF Data Services)

Procédure : exécuter des requêtes de service des données (WCF Data Services)

Procédure : ajouter des options de requête à une requête de service des données (WCF Data Services)

Procédure : déterminer le nombre d'entités retournées par une requête WCF Data Services

Procédure : spécifier les informations d'identification du client pour une demande de service de données (WCF Data Services)

Procédure : définir des en-têtes dans la demande cliente (WCF Data Services)

Procédure : projeter des résultats de requête (WCF Data Services)

Voir aussi

Autres ressources

Client de données (WCF Data Services)