Entity Framework - quelle est la différence entre l’utilisation du chargement Include / eager et du chargement différé?

eager-loading entity-framework lazy-loading

Question

J'ai essayé de me familiariser avec Entity Framework. La plupart des choses semblent simples, mais je suis un peu confus quant à la différence entre le chargement rapide avec la méthode Include et le chargement différé par défaut. Ils semblent tous les deux charger des entités apparentées, ce qui donne l'impression qu'ils font la même chose. Qu'est-ce que je rate?

Réponse acceptée

Supposons que vous ayez deux entités avec une relation un-à-plusieurs: Client et Commande, chaque client pouvant avoir plusieurs commandes.

Lors du chargement d'une entité client, Entity Framework vous permet de charger rapidement ou paresseusement la collection Orders du client. Si vous choisissez de charger rapidement la collection Orders, lorsque vous extrayez un client de la base de données, Entity Framework génère un code SQL qui extrait à la fois les informations du client et les commandes du client dans une requête. Toutefois, si vous choisissez de charger paresseusement la collection Orders, lorsque vous récupérez un client hors de la base de données, Entity Framework générera du SQL qui extraira uniquement les informations du client (Entity Framework générera alors une instruction SQL distincte si vous accédez ultérieurement à la collection Orders du client. dans votre code).

Déterminer à quel moment utiliser un chargement rapide et à quel moment utiliser un chargement paresseux dépend de ce que vous comptez faire avec les entités que vous récupérez. Si vous savez que vous avez uniquement besoin des informations d'un client, vous devez alors charger la collection Orders par laessence (pour que la requête SQL puisse être efficace en ne récupérant que les informations du client). Inversement, si vous savez que vous devez parcourir les commandes d'un client, vous devez alors charger les commandes avec impatience (pour vous éviter une frappe supplémentaire dans la base de données une fois que vous avez accédé aux commandes du client dans votre code).

Post-scriptum Soyez très prudent lorsque vous utilisez le chargement paresseux car cela peut conduire au problème N + 1. Par exemple, supposons qu'une page affiche une liste de clients et de leurs commandes. Cependant, vous décidez d'utiliser le chargement paresseux lors de la récupération des commandes. Lorsque vous parcourez la collection Customers, puis les commandes de chaque client, vous effectuez une recherche dans la base de données pour que chaque client charge paresseusement sa collection de commandes. Cela signifie que pour N clients, vous aurez N + 1 hits de base de données (1 hit de base de données pour charger tous les clients, puis N hits de base de données pour charger chacune de leurs commandes) au lieu d'un seul hit de base de données si vous aviez utilisé le chargement rapide (qui aurait récupéré tous les clients et leurs commandes dans une requête).


Réponse populaire

Si vous venez du monde SQL, pensez à JOIN.

Si vous devez afficher dans une grille 10 commandes et le client qui a passé la commande, vous avez 2 choix:

1) LAZY LOAD (= 11 requêtes = PERFORMANCES LENTES)

EF lancera une requête pour récupérer les commandes et une requête pour chaque commande pour récupérer les données du client.

Select * from order where order=1
+
10 x (Select * from customer where id = (order.customerId))

1) EAGER LOAD (= 1 requête = HIGH PERFORMANCES)

EF lancera une seule requête pour récupérer les commandes et les clients avec un JOIN.

Select * from orders INNER JOIN customers on orders.customerId=customer.Id where order=1

PS: lorsque vous récupérez un objet de la base de données, celui-ci est stocké dans une mémoire cache tant que le contexte est actif. Dans l'exemple que j'ai fait avec LAZY LOAD, si toutes les 10 commandes concernent le même client, vous ne verrez que 2 requêtes, car lorsque vous demandez à EF de récupérer un objet, celui-ci vérifie si l'objet est dans le cache et s'il le trouver ne déclenchera pas une autre requête SQL vers la base de données.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow