Requêtes d'objet (Entity Framework)

La classe générique ObjectQuery représente une requête qui peut retourner une collection de zéro, un ou plusieurs objets typés. Une classe ObjectQuery dépend d'un objet ObjectContext qui contient les informations de connexion et de métadonnées nécessaires à la composition et à l'exécution de la requête. Vous pouvez construire une requête ObjectQuery avec un opérateur new et transmettre une chaîne de requête et le contexte de l'objet au constructeur. Toutefois, il est plus courant d'utiliser les propriétés d'une classe dérivée ObjectContext pour obtenir une instance de ObjectQuery qui représente une collection de jeux d'entités. En règle générale, l'objet ObjectContext est sous-classé soit par une classe générée par les outils Entity Framework, soit par vos classes POCO. Par ailleurs, les propriétés du contexte de l'objet retournent des jeux d'entités sous forme d'ObjectQuery (dans la version 3.5 SP1 du .NET Framework) ou d'ObjectSet (dans la version 4 du .NET Framework). La classe ObjectSet étend la classe ObjectQuery pour fournir certaines fonctionnalités, telles que l'ajout et la suppression d'objets, dans le contexte d'un jeu d'entités typé.

La classe par défaut ObjectQuery fournit une requête initiale qui retourne toutes les entités du type spécifié. Cette requête peut être affinée à l'aide des méthodes de LINQ to Entities ou du Générateur de requêtes.

L'exemple suivant illustre une requête adressée au contexte de l'objet à propos de la collection de produits (Products).

Using context As New AdventureWorksEntities
    Dim products As ObjectSet(Of Product) = context.Products

    Dim productsQuery = _
        From product In products _
        Select product

    Console.WriteLine("Product Names:")
    For Each product In productsQuery
        Console.WriteLine(product.Name)
    Next
End Using
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    IQueryable<Product> productsQuery = from product in context.Products
                                        select product;

    Console.WriteLine("Product Names:");
    foreach (var prod in productsQuery)
    {
        Console.WriteLine(prod.Name);
    }
}

Exécution de requête

Une requête d'objet est exécutée quand :

Remarque : si par suite de l'exécution de la requête, rien n'est retourné de la source de données, les résultats contiennent une collection vide et non une valeur Null.

Les requêtes exécutées par Entity Framework sont évaluées par rapport aux données de la source de données et les objets nouveaux dans le contexte de l'objet ne sont pas représentés dans les résultats. Si une entité ayant la même identité que celle qui fait l'objet d'une requête est déjà attachée au contexte, les données en provenance de la source de données et les données déjà présentes dans le contexte sont fusionnées en fonction de l'option MergeOption de la requête. Pour obtenir les données présentes dans le cache, utilisez la méthode GetObjectStateEntries sur la classe ObjectStateManager. L'objet ObjectStateManager gère l'état des objets au sein d'un contexte d'objet, donc si vous souhaitez obtenir tous les objets ajoutés, modifiés et inchangés, vous pouvez passer une opération OR au niveau du bit des valeurs EntityState suivantes à la méthode GetObjectStateEntries : Added, Modified, Unchanged. Pour plus d'informations, consultez le blog qui montre comment effectuer des requêtes locales.

Dans l'exemple suivant, la méthode Execute est appelée pour exécuter une requête :

Using context As New AdventureWorksEntities()
    Dim query As ObjectSet(Of Product) = context.Products

    ' Execute the query and get the ObjectResult. 
    Dim queryResult As ObjectResult(Of Product) = query.Execute(MergeOption.AppendOnly)
    ' Iterate through the collection of Product items. 
    For Each result As Product In queryResult
        Console.WriteLine("{0}", result.Name)
    Next
End Using
using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    ObjectSet<Product> query = context.Products;

    // Execute the query and get the ObjectResult.
    ObjectResult<Product> queryResult = query.Execute(MergeOption.AppendOnly);
    // Iterate through the collection of Product items.
    foreach (Product result in queryResult)
        Console.WriteLine("{0}", result.Name);
}

Projection de requête

Les requêtes d'objet sont souvent utilisées pour retourner des données de modèle conceptuel sous forme d'objets entité. Or, elles peuvent aussi retourner un objet DbDataRecord pour les résultats imbriqués et les projections anonymes ou des types CLR primitifs pour les jeux de valeurs uniques.

LINQ to Entities et Entity SQL prennent tous deux en charge la projection de requête. Les considérations suivantes s'appliquent aux projections de requête :

  • Certaines méthodes d'extension requièrent de nombreux résultats sous forme de collection comme entrée. Si un objet ObjectQuery représente une requête qui retourne une collection avec un résultat scalaire unique, et que l'une de ces méthodes d'extension est appelée, une exception ArgumentException est levée, comme dans l'exemple suivant.

    ' Define a query projection that returns 
    ' a collection with a single scalar result.
    Dim scalarQuery As New ObjectQuery(Of Int32)("100", context)
    
    ' Calling an extension method that requires a collection 
    ' will result in an exception. 
    Dim hasValues As Boolean = scalarQuery.Any()
    
    // Define a query projection that returns 
    // a collection with a single scalar result.
    ObjectQuery<Int32> scalarQuery =
        new ObjectQuery<Int32>("100", context);
    
    // Calling an extension method that requires a collection
    // will result in an exception.
    bool hasValues = scalarQuery.Any();
    
  • Si un ObjectQuery peut retourner une valeur Null lorsqu'il est projeté vers un type primitif, vous devez utiliser la version Nullable du type. La requête suivante utilise un DateTime nullable car la propriété ShipDate de l'objet SalesOrderHeader peut retourner une valeur Null.

    Dim shipDateQuery As ObjectQuery(Of Nullable(Of DateTime)) = _
        context.SalesOrderHeaders.Where("it.CustomerID = @contactId", _
            New ObjectParameter("contactId", contactId)).SelectValue(Of Nullable(Of DateTime))("it.ShipDate")
    
    ObjectQuery<Nullable<DateTime>> shipDateQuery =
        context.SalesOrderHeaders
        .Where("it.CustomerID = @contactId",
            new ObjectParameter("contactId", contactId))
        .SelectValue<Nullable<DateTime>>("it.ShipDate");
    

    Pour plus d'informations, consultez Types Nullable (Guide de programmation Visual Basic) ou Nullable Types (C# Programming Guide).

Affichage des commandes de stockage

Lorsque vous exécutez une requête sur un modèle conceptuel, Entity Framework transforme les requêtes LINQ to Entities et les requêtes Entity SQL basées sur le modèle conceptuel en requêtes équivalentes exécutées sur la source de données. Entity Framework fournit les méthodes System.Data.Objects.ObjectQuery.ToTraceString et System.Data.EntityClient.EntityCommand.ToTraceString, qui permettent d'afficher ces commandes de stockage au moment de l'exécution sans qu'il soit nécessaire d'exécuter une trace sur la source de données. Pour plus d'informations, consultez Procédure : afficher les commandes de stockage (Entity Framework).

Récupération d'un objet par son EntityKey

Si vous connaissez la valeur de clé d'une entité, vous pouvez la récupérer à partir de la source de données sans créer et exécuter explicitement une requête d'objet. Les méthodes GetObjectByKey et TryGetObjectByKey de l'objet ObjectContext retournent alors un objet avec le EntityKey spécifié dans le contexte de l'objet. Lorsque vous utilisez la méthode GetObjectByKey, vous devez gérer un ObjectNotFoundException lorsque le EntityKey fourni ne correspond pas à une entité existante. Pour plus d'informations, voir Procédure : retourner un objet spécifique à l'aide de sa clé (Entity Framework).

Voir aussi

Concepts

Interrogation d'un modèle conceptuel (Entity Framework)
Utilisation d'ObjectSet (Entity Framework)
Requêtes compilées (LINQ to Entities)