Une requête avec des includes renvoie un seul ensemble de résultats et le nombre de includes affecte la manière dont l'ensemble de données est transféré du serveur de base de données au serveur web. Exemple :
Supposons que nous ayons une entité Customer (Id, Name, Address)
et une entité Order (Id, CustomerId, Date)
. Nous voulons maintenant interroger un client sur ses commandes :
var customer = context.Customers
.Include("Orders")
.SingleOrDefault(c => c.Id == 1);
L'ensemble de données obtenu aura la structure suivante :
Id | Name | Address | OrderId | CustomerId | Date
---------------------------------------------------
1 | A | XYZ | 1 | 1 | 1.1.
1 | A | XYZ | 2 | 1 | 2.1.
Cela signifie que Cutomers
sont répétées pour chaque Order
. Étendons maintenant l'exemple avec une autre entité - "OrderLine (Id, OrderId, ProductId, Quantity)". and
Produit (Id, Nom)`. Nous voulons maintenant interroger un client avec ses commandes, ses lignes de commande et ses produits :
var customer = context.Customers
.Include("Orders.OrderLines.Product")
.SingleOrDefault(c => c.Id == 1);
L'ensemble de données obtenu aura la structure suivante :
Id | Name | Address | OrderId | CustomerId | Date | OrderLineId | LOrderId | LProductId | Quantity | ProductId | ProductName
------------------------------------------------------------------------------------------------------------------------------
1 | A | XYZ | 1 | 1 | 1.1. | 1 | 1 | 1 | 5 | 1 | AA
1 | A | XYZ | 1 | 1 | 1.1. | 2 | 1 | 2 | 2 | 2 | BB
1 | A | XYZ | 2 | 1 | 2.1. | 3 | 2 | 1 | 4 | 1 | AA
1 | A | XYZ | 2 | 1 | 2.1. | 4 | 2 | 3 | 6 | 3 | CC
Comme vous pouvez le constater, les données sont souvent dupliquées. En général, chaque inclusion à une propriété de navigation de référence ( Product
dans l'exemple) ajoutera de nouvelles colonnes et chaque inclusion à une propriété de navigation de la collection ( Orders
y OrderLines
dans l'exemple) ajoutera de nouvelles colonnes et dupliquera les lignes déjà créées pour chaque ligne de la collection incluse.
Cela signifie que votre exemple peut facilement comporter des centaines de colonnes et des milliers de lignes, ce qui représente beaucoup de données à transférer. La bonne approche consiste à créer des tests de performance et si le résultat ne répond pas à vos attentes, vous pouvez modifier votre requête et charger les propriétés de navigation séparément avec leurs propres requêtes ou par LoadProperty
méthode.
Exemple de requêtes distinctes :
var customer = context.Customers
.Include("Orders")
.SingleOrDefault(c => c.Id == 1);
var orderLines = context.OrderLines
.Include("Product")
.Where(l => l.Order.Customer.Id == 1)
.ToList();
Exemple de LoadProperty
:
var customer = context.Customers
.SingleOrDefault(c => c.Id == 1);
context.LoadProperty(customer, c => c.Orders);
De même, vous ne devez charger que les données dont vous avez réellement besoin.
Editer : Je viens de créer proposition sur les données UserVoice pour prendre en charge une stratégie supplémentaire de chargement anticipé, dans le cadre de laquelle les données chargées anticipativement seraient transmises dans un ensemble de résultats supplémentaire (créé par une requête distincte au cours d'un même aller-retour dans la base de données). Si vous trouvez cette amélioration intéressante, n'oubliez pas de voter pour la proposition.