Paresseux vs désireux de chargement de la performance sur Entity Framework

J'ai donc le modèle suivant les classes sur mon DbContext:

Paresseux vs désireux de chargement de la performance sur Entity Framework

Chaque fois que j'ai rendu une liste de LoanApplication objets-je faire quelque chose comme ceci:

var context = new MyContext();
var applications = context.LoanApplications.Where(d => d.PropertyThatIWantToFilter = localVariable);

Il renvoie un IQueryable que puis-je convertir à un ViewModel de ce genre sur mon contrôleur de l'appel de la méthode:

var vm = applications.Select(d => new LoanApplicationViewModel(d));

À l'intérieur de la LoanApplicationViewModel constructeur j'accepte l'entité de l'objet et de faire le correspondant de la cartographie. Le truc, c'est que, depuis que les Avocats de la collection est une de navigation de la propriété, un appel est fait à la base de données chaque fois qu'un nouveau modèle de vue est instanciée. La moyenne du nombre d'avocats par demande est de deux, ce qui veut dire que si je le rendu d'un tableau listant les 10 dernières applications de l'app est de faire environ 18-20 voyages à la base de données.

J'ai pensé qu'il y avait une meilleure façon d'obtenir cette collection, j'ai donc modifié ma requête initiale à avec impatience charge de la collecte de la sorte:

var applications = context.LoanApplications.Include("Solicitors").Where...

Bien que cela réduit le nombre d'appels à la base de données à un seul, la requête a été beaucoup plus lent, environ 50% plus lent.

La base de données est hébergée sur SQL Azure, et nous avons mis en œuvre Transitoire de gestion des Pannes, mais je veux réduire la quantité d'appels à la base de données, sans réduire le temps de réponse de la performance.

Quelle est la meilleure pratique ici?

dans la pure efficacité, désireux de chargement est supérieure. Si la frappe initiale pousse un seuil, vous devriez reconsidérer. Si votre lazy load n'aurait pas besoin de plus de 20% de données supplémentaires, chanceler. Mais en cisaillement mesure de données extracteur vs brut en temps de frapper, désireux de chargement gagne toujours.
Vous ne pouvez pas avoir les deux - c'est à propos de faire le meilleur compromis je dirais soit désireux de charge/Include (je serai d'accord que c'est la meilleure si nécessaire) - si vous avez besoin de les avoir dès le début. Ou ne se charge pas du tout - pas désireux de charge. Puis plus tard, ne Reload pour une entité, vous devez avoir à jour (c'est à dire que vous n'avez pas l'impact initial) - ou vous pouvez le faire, d'automatiser/intégrer dans quelque chose de plus intelligent. Ce n'est pas idéal, rien n'est - mais c'est ce que vous obtenez.
Comme ma réponse ci-dessous, le profil. Peut-être que les avocats ont déjà été chargé dans MyContext avant. (Vous ne sont sûrement pas la création d'un nouveau contexte pour chaque requête, non?) Ou peut-être votre modèle de vue .Sélectionnez omettre db colonnes qui a beaucoup de MO de données?
Aussi, je recommande de ne pas passer IQueryable autour de l'application. Vous n'avez aucun moyen de savoir ce que la Requête a déjà été appliqué lorsque vous le passer autour et il fait des essais difficiles. (Tout est maintenant lié à QueryProvider dans le IQueryable, et la seule façon de vérifier si la requête est traduite correctement est de l'exécuter à l'encontre de SQL. Ensuite, les gens juste de commencer à cogner avec une Liste<T>, et faire un désordre complet, et les analyses, puis ne prouve rien, comme une Requête contre la Liste<T> ne l'est pas forcément traduire correctement en SQL et s'exécute correctement sur SQL.)

OriginalL'auteur amhed | 2013-04-03