Share via


Flux d'exécution LINQ to Entities

Les requêtes exécutées avec Entity Framework sont représentées par des requêtes d'arborescence de commandes, lesquelles s'exécutent par rapport au contexte de l'objet. LINQ to Entities convertit les requêtes LINQ (Language-Integrated Query) en requêtes d'arborescence de commandes, exécute les requêtes avec Entity Framework, puis retourne les objets qui peuvent être utilisés aussi bien par Entity Framework que par LINQ. Voici le processus de création et d'exécution d'une requête LINQ to Entities :

  1. Construisez une instance de l'objet ObjectQuery à partir de l'objet ObjectContext.

  2. Composez une requête LINQ to Entities en C# ou en Visual Basic en utilisant l'instance de l'objet ObjectQuery.

  3. Convertissez les expressions et opérateurs de requête standard LINQ en arborescences de commandes.

  4. Exécutez la requête dans l'arborescence des commandes sur la source de données. Toutes les exceptions levées sur la source de données pendant l'exécution sont passées directement au client.

  5. Retournez les résultats de la requête au client.

Construction d'une instance d'ObjectQuery

La classe générique ObjectQuery représente une requête qui retourne une collection de zéro ou plusieurs entités typées. Une requête d'objet est généralement construite à partir d'un contexte d'objet existant, au lieu d'être construite manuellement, et appartient toujours à ce contexte d'objet. Ce contexte fournit les informations relatives à la connexion et aux métadonnées qui sont requises pour composer et exécuter la requête. La classe générique ObjectQuery implémente l'interface générique IQueryable, dont les méthodes de générateur permettent la construction de façon incrémentielle des requêtes LINQ.

Composition de la requête

Les instances de la classe générique ObjectQuery, laquelle implémente l'interface générique IQueryable, servent de source de données pour les requêtes LINQ to Entities. Dans une requête, vous spécifiez exactement les informations que vous voulez récupérer à partir de la source de données. Une requête peut également spécifier la manière dont ces informations doivent être triées, regroupées et mises en forme avant d'être retournées. Dans LINQ, une requête est stockée dans une variable. Cette variable de requête n'effectue aucune action et ne retourne aucune donnée ; elle stocke uniquement les informations de requête. Une fois que vous avez créé une requête, vous devez l'exécuter pour extraire des données.

Les requêtes LINQ to Entities peuvent être composées dans deux syntaxes différentes : la syntaxe d'expression de requête et la syntaxe de requête fondée sur une méthode. La syntaxe d'expression de requête et la syntaxe de requête fondée sur une méthode sont nouvelles dans C# 3.0 et dans Visual Basic 9.0.

Pour plus d'informations, voir Requêtes dans LINQ to Entities.

L'exemple suivant de syntaxe d'expression de requête construit une instance de l'objet ObjectQuery à partir du contexte d'objet d'AdventureWorks et utilise Select pour retourner toutes les lignes de Product.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p

End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productNames =
       from p in products
       select p;
}

L'exemple suivant de syntaxe de requête fondée sur une méthode construit une instance de l'objet ObjectQuery à partir du contexte d'objet d'AdventureWorks et utilise Select pour retourner toutes les lignes de Product.

Using AWEntities As New AdventureWorksEntities


    Dim productNames = AWEntities.Product.Select(Function(p) p.Name)

End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productNames = products.Select(p => p);

}

Conversion de requête

Pour exécuter une requête LINQ to Entities avec Entity Framework, cette requête doit être convertie en représentation arborescente des commandes qui peut être exécutée avec Entity Framework.

Les requêtes LINQ to Entities sont constituées d'opérateurs de requête standard LINQ (tels que Select, Where et GroupBy) et d'expressions (x > 10, Contact.LastName, etc.). Les opérateurs LINQ ne sont pas définis par une classe ; ce sont des méthodes sur une classe. Dans LINQ, les expressions peuvent contenir tout ce que les types de l'espace de noms System.Linq.Expressions autorisent et, par extension, tout ce qui peut être représenté dans une fonction lambda. Il s'agit d'un sur-ensemble des expressions qui sont autorisées par Entity Framework, lesquelles sont, par définition, limitées aux opérations autorisées sur la base de données et prises en charge par l'objet ObjectQuery.

Dans Entity Framework, les opérateurs et les expressions sont représentés par une seule hiérarchie des types, qui sont ensuite placés dans une arborescence de commandes. L'arborescence de commandes est utilisée par Entity Framework pour exécuter la requête. Si la requête LINQ ne peut pas être exprimée sous la forme d'une arborescence de commandes, une exception est levée au moment de la conversion de la requête. La conversion de requêtes LINQ to Entities implique deux sous-conversions : la conversion des opérateurs de requête standard et la conversion des expressions.

Plusieurs opérateurs de requête standard LINQ n'ont pas de traduction valide dans LINQ to Entities. Les tentatives d'utilisation de ces opérateurs provoquent une exception au moment de la traduction de la requête. Pour obtenir la liste des opérateurs LINQ to Entities pris en charge, voir Méthodes prises en charge et non prises en charge (LINQ to Entities).

Pour plus d'informations sur l'utilisation des opérateurs de requête standard dans LINQ to Entities, voir Opérateurs de requête standard dans les requêtes LINQ to Entities.

En règle générale, les expressions dans LINQ to Entities sont évaluées sur le serveur. Par conséquent, le comportement de l'expression n'est pas censé suivre la sémantique CLR. Pour plus d'informations, voir Expressions dans les requêtes LINQ to Entities.

Exécution de la requête

Une fois la requête LINQ créée par l'utilisateur, elle est convertie en une représentation compatible avec Entity Framework (sous la forme d'arborescences de commandes), qui est ensuite exécutée sur la source de données. Au moment de l'exécution de la requête, l'ensemble des expressions de requête (ou des composants de la requête) sont évalués sur le client ou sur le serveur. Cela comprend les expressions qui sont utilisées dans la matérialisation des résultats ou les projections d'entités.

Le moment d'exécution d'une expression de requête peut varier. Les requêtes LINQ sont exécutées chaque fois que la variable de requête est parcourue, et non pas au moment de la création de la variable de requête ; ce procédé est appelé « exécution différée ». La requête peut également être forcée à s'exécuter immédiatement, ce qui est utile pour mettre en cache les résultats de la requête. L'exemple suivant utilise Select pour retourner toutes les lignes de Product et afficher les noms de produits. L'itération sur la variable de requête dans la boucle foreach/For Each entraîne l'exécution de la requête.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p.Name

    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames =
       from p in products
       select p.Name;

    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

Lorsqu'une requête LINQ to Entities est exécutée, il est possible que certaines expressions de la requête soient exécutées sur le serveur et que certaines parties soient exécutées localement sur le client. L'évaluation côté client d'une expression a lieu avant l'exécution de la requête sur le serveur. Si une expression est évaluée sur le client, le résultat de cette évaluation remplace l'expression de la requête, et la requête est ensuite exécutée sur le serveur. Étant donné que les requêtes sont exécutées sur la source de données, la configuration de la source de données prévaut sur le comportement spécifié dans le client. La gestion des valeurs Null et la précision numérique en sont des exemples. Toutes les exceptions levées pendant l'exécution de la requête sur le serveur sont passées directement au client. Pour plus d'informations, voir Exécution de requête.

Matérialisation

La matérialisation est le processus qui consiste à retourner les résultats d'une requête au client sous forme de types CLR. Dans LINQ to Entities, les enregistrements de données des résultats de requête ne sont jamais retournés ; il y a toujours un type CLR de sauvegarde, défini par l'utilisateur ou par Entity Framework, ou généré par le compilateur (types anonymes). Toute matérialisation d'objets est effectuée par Entity Framework. Toute erreur qui résulte d'une impossibilité d'effectuer un mappage entre Entity Framework et le CLR lève une exception à lever pendant la matérialisation d'objets.

Les résultats de la requête sont généralement retournés sous l'une des formes suivantes :

  • Une collection de zéro ou plusieurs objets entité typés ou une projection de types complexes dans le modèle EDM.

  • Types CLR pris en charge par le modèle EDM.

  • Collections inline.

  • Types anonymes.

Pour plus d'informations, voir Résultats de requête.

Voir aussi

Autres ressources

Exécution de requêtes avec LINQ to Entities