Chargement d'objets connexes (Entity Framework)

Cette rubrique décrit les modèles que vous pouvez utiliser pour charger des entités connexes. Les types d'entité peuvent définir des propriétés de navigation qui représentent des associations dans le modèle de données. Vous pouvez utiliser ces propriétés pour charger les entités associées à l'entité retournée par l'association définie. Lorsque des entités sont générées selon le modèle de données, des propriétés de navigation sont générées pour les entités aux deux terminaisons d'une association. Ces propriétés de navigation retournent soit une référence à la terminaison « un » d'une relation un-à-un ou plusieurs-à-un ou une collection à la terminaison « plusieurs » d'une relation un-à-plusieurs ou plusieurs-à-plusieurs. Pour plus d'informations, consultez Propriétés de navigation et Définition et gestion des relations (Entity Framework).

Les modèles suivants décrivent les différentes manières dont vous pouvez charger des entités connexes :

Modèle de chargement Description

Spécifié dans la requête

Vous pouvez composer une requête Entity SQL ou LINQ to Entities qui parcourt explicitement les relations en utilisant des propriétés de navigation. Lorsque vous exécutez une telle requête, les entités connexes qui sont incluses en tant que propriétés de navigation dans la projection de la requête sont retournées. Pour plus d'informations, consultez

Procédure : explorer des relations à l'aide des propriétés de navigation (Entity Framework).

Chargement explicite

Le chargement explicite d'entités dans le ObjectContext requiert plusieurs allers-retours à la base de données et peut nécessiter plusieurs jeux de résultats actifs, mais la quantité de données retournées se limite aux seules entités chargées. Utilisez la méthode Load sur un objet EntityCollection ou EntityReference ou la méthode LoadProperty sur l'objet ObjectContext pour récupérer explicitement les entités connexes à partir de la source de données. Chaque appel à la méthode Load ouvre une connexion à la base de données pour récupérer les informations associées. Cela garantit qu'une requête n'est jamais exécutée sans une demande explicite pour l'entité connexe. Le chargement explicite correspond au comportement par défaut d'Entity Framework .

Bb896272.note(fr-fr,VS.100).gifRemarque :
Avant que Load soit appelé, une petite partie des informations concernant l'entité connexe est déjà chargée dans ObjectContext.

Pour plus d'informations, consultez la section Explicitly Loading Related Objects de cette rubrique.

Chargement différé

Dans ce type de chargement, les entités connexes sont chargées automatiquement à partir de la source de données lorsque vous accédez à une propriété de navigation. Avec ce type de chargement, soyez conscient que chaque propriété de navigation à laquelle vous accédez provoque l'exécution d'une requête distincte sur la source de données, si l'entité ne figure pas encore dans ObjectContext.

Pour plus d'informations, consultez la section Lazy Loading de cette rubrique.

Chargement hâtif

ou

Définition de chemins d'accès de requête avec Include

Lorsque vous connaissez la forme exacte du graphique des entités connexes que votre application requiert, vous pouvez utiliser la méthode Include sur ObjectQuery pour définir un chemin d'accès de requête qui contrôle les entités connexes à retourner dans le cadre de la requête initiale. Lorsque vous définissez un chemin d'accès de requête, il suffit d'adresser une demande unique à la base de données pour que toutes les entités définies par le chemin d'accès soient retournées dans un jeu de résultats unique, et toutes les entités connexes du type spécifié dans le chemin d'accès sont chargées avec chaque objet que la requête retourne.

Pour plus d'informations, consultez la section Defining a Query Path to Shape Query Results de cette rubrique.

Chargement explicite d'objets entités connexes

Pour charger explicitement des entités connexes, vous devez appeler la méthode Load sur la terminaison connexe retournée par la propriété de navigation. Dans le cas d'une relation un-à-plusieurs, appelez la méthode Load sur EntityCollection ; dans le cas d'une relation un-à-un, appelez la méthode Load sur EntityReference. Si vous utilisez des entités POCO, utilisez la méthode LoadProperty sur le ObjectContext. Pour plus d'informations, consultez Chargement d'entités POCO connexes (Entity Framework). La méthode LoadProperty peut également être utilisée avec les entités dérivées de EntityObject. Ces méthodes chargent les données d'objets connexes dans le contexte de l'objet. Lorsqu'une requête retourne des résultats, vous pouvez énumérer la collection d'objets à l'aide d'une boucle foreach (For Each...Next en Visual Basic) et appeler de manière conditionnelle la méthode Load sur les propriétés EntityReference et EntityCollection pour chaque entité dans les résultats.

Bb896272.note(fr-fr,VS.100).gifRemarque :
Lorsque vous appelez la méthode Load lors d'une énumération foreach (C#) ou For Each (Visual Basic), Entity Framework essaie d'ouvrir un nouveau lecteur de données.Cette opération échoue sauf si vous avez activé des ensembles de résultats actifs multiples (MARS) en spécifiant multipleactiveresultsets=true dans la chaîne de connexion.Pour plus d'informations, voir Utilisation des ensembles de résultats actifs multiples (MARS) sur MSDN.Vous pouvez également charger le résultat de la requête dans une collection List, ce qui a pour effet de fermer le lecteur de données et de vous permettre d'énumérer la collection pour charger les entités référencées.

Pour plus d'informations, consultez Procédure : charger explicitement des objets connexes (Entity Framework).

Définition d'un chemin d'accès de requête pour mettre en forme les résultats de requête

Pour spécifier le chemin d'accès de la requête, transmettez une représentation de chaîne du graphique d'objet à la méthode Include sur la classe ObjectQuery. Ce chemin d'accès indique quelles entités connexes retourner lors de l'exécution d'une requête d'objet. Par exemple, si vous définissez un chemin d'accès dans une requête pour des objets Contact, vous serez assuré que chaque objet connexe SalesOrderHeader et SalesOrderDetail sera retourné. Ce cas est présenté dans la requête suivante :

' Define a LINQ query with a path that returns 
' orders and items for a contact. 
Dim contacts = (From contact In context.Contacts.Include("SalesOrderHeaders.SalesOrderDetails") _
    Select contact).FirstOrDefault()
// Define a LINQ query with a path that returns 
// orders and items for a contact.
var contacts = (from contact in context.Contacts
              .Include("SalesOrderHeaders.SalesOrderDetails")
                select contact).FirstOrDefault();

Au moment de définir des chemins d'accès de requête, vous devez tenir compte des points suivants :

  • Les chemins d'accès de requête peuvent être utilisés avec les méthodes du Générateur de requêtes et les requêtes LINQ.

  • Lorsque vous appelez Include, le chemin d'accès de la requête n'est valide que sur l'instance retournée de ObjectQuery. Les autres instances de ObjectQuery et le contexte d'objet lui-même ne sont pas affectés.

  • Comme Include retourne l'objet de requête, vous pouvez appeler cette méthode à plusieurs reprises sur un ObjectQuery pour inclure les entités de plusieurs relations, comme dans l'exemple suivant :

    ' Create a SalesOrderHeader query with two query paths, 
    ' one that returns order items and a second that returns the 
    ' billing and shipping addresses for each order. 
    Dim query As ObjectQuery(Of SalesOrderHeader) = context.SalesOrderHeaders.Include("SalesOrderDetails").Include("Address")
    
    // Create a SalesOrderHeader query with two query paths, 
    // one that returns order items and a second that returns the 
    // billing and shipping addresses for each order.
    ObjectQuery<SalesOrderHeader> query =
        context.SalesOrderHeaders.Include("SalesOrderDetails").Include("Address");
    
  • L'utilisation de chemins d'accès de requête peut se traduire par l'exécution de commandes complexes sur la source de données à partir de requêtes d'objet simples d'apparence. Cela se produit parce qu'une ou plusieurs jointures sont requises pour retourner les objets connexes dans une requête unique, ce qui entraîne des données redondantes pour chaque entité connexe qui est retournée à partir de la source de données. Cette complexité est plus prononcée dans le cas de requêtes exécutées sur un modèle complexe, par exemple, une entité avec héritage ou un chemin d'accès qui inclut des relations plusieurs-à-plusieurs. Utilisez la méthode ToTraceString pour voir la commande qui sera générée par un ObjectQuery. Lorsqu'un chemin d'accès de requête comprend un trop grand nombre d'objets connexes ou que les objets contiennent une trop grande quantité de données de ligne, la source de données risque de ne pas être en mesure de faire aboutir la requête. Cela se produit si la requête a besoin d'un stockage temporaire intermédiaire qui dépasse les capacités de la source de données. En pareil cas, vous pouvez réduire la complexité de la requête de source de données en chargeant explicitement les objets connexes ou en activant le chargement différé. Si après avoir optimisé une requête complexe vous constatez toujours de fréquents délais d'attente, envisagez d'augmenter la valeur du délai d'attente en définissant la propriété CommandTimeout.

Pour plus d'informations, consultez Procédure : utiliser des chemins d'accès de requête pour personnaliser des résultats (Entity Framework).

Chargement différé d'objets entité

Entity Framework prend en charge le chargement différé des entités connexes. Au moment de l'exécution d'Entity Framework , la valeur par défaut de la propriété LazyLoadingEnabled dans une instance d'un objet ObjectContext est false. Toutefois, si vous utilisez les outils Entity Framework pour créer un nouveau modèle et les classes générées correspondantes, LazyLoadingEnabled a la valeur true dans le constructeur du contexte de l'objet. Lorsque le chargement différé est activé, les entités connexes sont chargées à partir de la source de données seulement lorsque l'accesseur get d'une propriété de navigation accède par programmation à ces entités. Pour désactiver le chargement différé, affectez à la propriété LazyLoadingEnabled la valeur false sur l'instance de ObjectContextOptions qui est retournée par la propriété System.Data.Objects.ObjectContext.ContextOptions.

Le chargement différé peut être utilisé avec le chargement hâtif. De cette manière, un graphique de données de base peut être défini à l'aide des chemins d'accès de requête et des entités connexes supplémentaires, non incluses dans les chemins d'accès de requête d'origine, peuvent être chargées au besoin. Pour plus d'informations, consultez Procédure : utiliser le chargement différé pour charger des objets connexes (Entity Framework).

Les éléments suivants doivent être considérés lorsque vous utilisez le chargement différé :

  • Le chargement différé est pris en charge pour les propriétés de navigation qui retournent à la fois une entité unique (telle qu'une EntityReference) et une collection d'entités (telle qu'une EntityCollection).

  • Si le chargement différé est activé et qu'une entité connexe est déjà chargée, elle ne sera pas chargée une nouvelle fois.

  • Le chargement différé est pris en charge pour les entités dans un état Detached. Dans ce cas, les objets connexes sont également retournés dans un état Detached.

  • Le comportement du chargement différé est déterminé par l'instance de la classe ObjectContext qui est utilisée pour récupérer l'objet à partir de la source de données (même si l'entité a été chargée avec le NoTracking MergeOption) ou à laquelle l'objet a été ajouté ou joint. De ce fait, le comportement du chargement différé ne peut pas être modifié une fois que ce contexte a été supprimé et toutes les opérations de chargement différé ultérieures échoueront.

  • Lors de la sérialisation d'entités, envisagez de désactiver le chargement différé. Sinon, le chargement différé sera déclenché et les entités sérialisées pourront inclure plus de données que prévu.

Des considérations supplémentaires s'appliquent lorsque vous utilisez le chargement différé avec des entités POCO. Pour plus d'informations, consultez Chargement d'entités POCO connexes (Entity Framework).

Interrogation d'objets entité connexes

L'appel de la méthode CreateSourceQuery sur unEntityCollection vous permet d'interroger des objets connexes sans charger au préalable les objets dans la collection. La méthode CreateSourceQuery retourne un objet ObjectQuery qui, lorsqu'il est exécuté, retourne le même jeu d'objets que la méthode Load. Vous pouvez appliquer des méthodes du Générateur de requêtes à cette requête d'objet pour filtrer davantage les objets chargés dans la collection. Pour plus d'informations, consultez Procédure : interroger les objets connexes d'un objet EntityCollection (Entity Framework).

Un objet ObjectQuery retourne les données d'entité sous la forme d'entités. Toutefois, lorsqu'une propriété de navigation est incluse dans la projection de requête, la requête retourne également les entités connexes auxquelles la navigation a accédé. Pour plus d'informations, consultez Procédure : explorer des relations à l'aide des propriétés de navigation (Entity Framework).

Considérations sur les performances

Lorsque vous choisissez un modèle pour le chargement des entités connexes, considérez le comportement de chaque approche en ce qui concerne le nombre et le minutage des connexions établies avec la source de données par rapport à la quantité de données retournée par une requête unique et la complexité d'utiliser une requête unique. Le chargement hâtif retourne toutes les entités connexes avec les entités interrogées dans une requête unique. Cela signifie que, bien qu'une seule connexion soit établie avec la source de données, une plus grande quantité de données est retournée dans la requête initiale. Également, les chemins d'accès de requête génèrent une requête plus complexe en raison des jointures supplémentaires qui sont requises dans la requête exécutée sur la source de données.

Le chargement explicite et différé vous permet de remettre la demande des données d'objet connexe au moment où ces données seront réellement exigées. Il en résulte une requête initiale moins complexe qui retourne moins de données au total. Toutefois, chaque chargement successif d'un objet connexe établit une connexion avec la source de données et exécute une requête. Dans le cas du chargement différé, cette connexion se produit chaque fois que vous accédez à une propriété de navigation et que l'entité connexe n'est pas déjà chargée. Si vous souhaitez identifier les entités connexes qui sont retournées par la requête initiale ou décider du moment où les entités connexes sont chargées à partir de la source de données, vous devez envisager de désactiver le chargement différé. Le chargement différé est activé dans le constructeur du contexte de l'objet généré par Entity Framework .

Pour plus d'informations, consultez Considérations sur les performances (Entity Framework).

Voir aussi

Concepts

Interrogation d'un modèle conceptuel (Entity Framework)
Requêtes d'objet (Entity Framework)
Méthodes du Générateur de requêtes (Entity Framework)