2010-04-27 3 views
2

Je reçois un comportement inattendu avec entité framework 4.0 et j'espère que quelqu'un peut m'aider à comprendre cela. J'utilise la base de données Northwind pour les besoins de cette question. J'utilise également le générateur de code par défaut (pas poco ou auto-suivi). Je m'attends à ce que chaque fois que j'interroge le contexte de la structure pour faire seulement un aller-retour si je n'ai pas déjà récupéré ces objets. J'obtiens ce comportement si j'éteins le chargement paresseux. Actuellement, dans mon application, je suis brusquement en train de faire un chargement paresseux, puis je l'éteins pour que je puisse obtenir le comportement désiré. C'est presque nul, alors aidez s'il vous plaît. Voici un bon exemple de code qui peut démontrer mon problème.Aidez-moi à comprendre le cadre d'entité 4 mise en cache pour le chargement paresseux

Public Sub ManyRoundTrips() 
    context.ContextOptions.LazyLoadingEnabled = True 
    Dim employees As List(Of Employee) = context.Employees.Execute(System.Data.Objects.MergeOption.AppendOnly).ToList() 

    'makes unnessesary round trip to the database, I just loaded the employees' 
    MessageBox.Show(context.Employees.Where(Function(x) x.EmployeeID < 10).ToList().Count) 
    context.Orders.Execute(System.Data.Objects.MergeOption.AppendOnly) 
    For Each emp As Employee In employees 
     'makes unnessesary trip to database every time despite orders being pre loaded.' 
     Dim i As Integer = emp.Orders.Count 
    Next 
End Sub 

Public Sub OneRoundTrip() 
    context.ContextOptions.LazyLoadingEnabled = True 
    Dim employees As List(Of Employee) = context.Employees.Include("Orders").Execute(System.Data.Objects.MergeOption.AppendOnly).ToList() 

    MessageBox.Show(employees.Where(Function(x) x.EmployeeID < 10).ToList().Count) 

    For Each emp As Employee In employees 
     Dim i As Integer = emp.Orders.Count 
    Next 
End Sub 

Pourquoi le premier bloc de code rend-il les allers-retours unnesses?

Répondre

3

Vos attentes sont inexactes. Les requêtes toujours interrogent la base de données. Toujours. C'est parce que LINQ est toujours converti en SQL.

Pour charger un objet à partir du contexte s'il a déjà été récupéré et à partir de la base de données si ce n'est pas le cas, utilisez ObjectContext.GetObjectByKey().

2

Le premier déplacement «inutile» est nécessaire: vous avez effectué une nouvelle requête et la base de données a pu être modifiée entre-temps. Si vous avez utilisé la variable employees à la place (où vous avez stocké le résultat de la requête), il n'aurait pas besoin de se rendre à la base de données. Le deuxième est nécessaire parce que vous lui demandez d'aller chercher les commandes pour chaque employé. Avec le chargement paresseux et sans Include() il n'a pas lu les commandes jusqu'à ce que vous le demandiez avec emp.Orders.Count(). N'oubliez pas que jusqu'à ce que vous commenciez à itérer sur une requête (ou appelez une méthode qui l'exige pour itérer), LINQ to EF ne fait rien. Si vous enregistrez cette requête dans une variable, puis appelez .Count(), il y aura un aller-retour. Si vous utilisez la même requête et commencez à l'énumérer, il y aura un autre aller-retour. Si les entités de cette requête ont elles-mêmes des relations et un chargement paresseux à chaque fois que vous en accédez, il y aura encore un autre aller-retour.

Votre deuxième exemple montre comment faire ceci correctement si vous savez à l'avance que vous voulez que les ordres, c'est désireux de chargement. Remarquez comment vous ne revenez pas au contexte pour le demander à nouveau aux employés, vous réutilisez celui que vous avez déjà chargé.

+0

Ok a joué avec certains paramètres dans le scénario que vous avez décrit au paragraphe deux. Je suis toujours confus. Si je désactive le chargement paresseux, cela me donne les résultats que je veux sans un autre aller-retour dans la base de données. Si j'active le chargement paresseux, cela fait l'aller-retour. Parfois, je ne peux pas mettre tout ce dont j'ai besoin dans l'inclusion ou la performance de cette requête car elle est si énorme. Alors pourquoi ai-je les deux comportements quand j'éteins le chargement paresseux? – Chris

Questions connexes