Récupérer une entité par son identifiant est quelque chose que l’on fait quotidiennement dans nos applications, mais le fait-on vraiment correctement ?
Une histoire de performance
Vous me direz, comment peut-on mal faire quelque chose d’aussi simple ? Et je vous répondrai tout simplement, faites comme moi et ne lisez pas la documentation des choses que vous pensez aussi simple.
Penchons-nous un peu sur la documentation de la méthode Find de l’implémentation du DbSet d’EF Core.
Finds an entity with the given primary key values. If an entity with the given primary key values is being tracked by the context, then it is returned immediately without making a request to the database. Otherwise, a query is made to the database for an entity with the given primary key values and this entity, if found, is attached to the context and returned. If no entity is found, then null is returned.
Plutôt explicite non ? Pour les anglophobes, la documentation nous explique que la méthode permet de chercher une entité via la clef primaire passée en paramètre. Si cette clef est déjà traquée par le contexte, l’entité sera directement retournée sans faire de requête vers la base de données, sinon, l’entité sera attachée et ensuite retournée.
Find() Vs SingleOrDefault(), implémentation
Concrètement, voici ce que ça donnerait au niveau du code :
// Find
var beer = context.Find(2); // Une requête est exécutée, l’entité n’étant pas encore traqués, EF va exécuter une requête vers la Db, traquer l’entité et la renvoyer
var secondBeer = context.Find(2); // L’entité est déjà traqué, EF va directement retourner l’entité correspondante
// SingleOrDefault
var beer = context.SingleOrDefault(b => b.Id == 2); // EF va exécuter la requête vers la Db et renvoyer l’entité
var secondBeer = context.SingleOrDefault(b => b.Id == 2); // EF va à nouveau exécuter la requête, sans tenir compte du contexte
// Mélange des deux
var beer = context.SingleOrDefault(b => b.Id == 2); // EF va exécuter la requête vers la Db et renvoyer l’entité
var secondBeer = context.Find(2); // L’entité est traqué par le contexte car récupéré précédemment, aucune requête ne partira vers la Db
Petite subtilité, bien que SingleOrDefault() (ou FirstOrDefault() / First() / Single()) ne tienne pas compte des entités traquée pour renvoyer son résultat, cette méthode rajoute quand même l’entité au contexte actuel. Ce qui nous donne le 3ème cas d’exemple où Find() tire profit des entités traquées par les autres méthodes pour éviter un aller / retour.
Avantages de Find()
- Éviter des allers / retours inutiles vers la base de données
- Méthode propre au DbSet, on ne dépend pas de Linq
Inconvénients de Find()
- Ne permets les recherches que par la clef primaire
En conclusion
C’est, selon moi, une petite habitude à prendre qui nous permet, dans certains cas, d’optimiser le chargement de nos entités, alors pourquoi s’en priver ? Je n’utilise désormais plus que Find() quand je dois récupérer des données par l’identifiant primaire.
Et vous, quelle petite spécifité du quotidien avez-vous rencontrée récemment ? Saviez-vous que Find() permettait cette petite optimisation ?
Be First to Comment