2009-10-22 5 views
1

J'ai cela pour chaque boucleLINQ aux objets vs pour chaque - différence dans les horaires d'exécution

foreach (Account acct in acctTest) 
      { 
       if (acct.AccountId == acctId) 
       { 
        foreach (Customer cust in acct.CustomerColl) 
        { 
         if (cust.CustomerId == custId) 
         { 
          customerName = cust.CustomerName; 
          break; 
         } 
        } 
       } 
      } 

requête Linq qui fait des choses similaires (pense que cela peut être amélioré)

customerName = (from acct in acctTest 
          where acct.AccountId == acctId 
          from cust in acct.CustomerColl 
          where cust.CustomerId == custId 
          select cust.CustomerName).ToString() ; 

J'exercerai les deux ci-dessus dans une boucle de 1000 fois pendant 5 fois, obtenir les horaires d'exécution comme ci-dessous.

temps écoulé pour Pour chaque ::: 7377
Durée des Linq2 ::: 15653
temps écoulé pour Pour chaque 1576 :::
temps écoulé pour Linq2 ::: 1718
temps écoulé pour Pour chaque ::: 1569
durée des Linq2 ::: 1726
temps écoulé pour pour chaque 1569 :::
temps écoulé pour Linq2 ::: 5583
temps écoulé pour pour chaque 1570
::: Elapsed temps pour Linq2 :: : 1506

pourquoi existe-t-il une différence et une incohérence dans les temps d'exécution? De même, existe-t-il un moyen de réécrire la requête LINQ pour de meilleures performances?

+1

Vous devez utiliser 'FirstOrDefault', pas' ToString' dans votre requête. –

+0

oui, en utilisant FirstOrDefault comme suggéré par vous et KristoferA rend la requête linq plus rapide – jbagavathi

Répondre

2
(from acct in acctTest 
where acct.AccountId == acctID 
select acct.CustomerColl) 
    .Where(c => c.CustomerId == custId) 
    .Select(cn => cn.CustomerName) 
    .FirstOrDefault() 
+0

en dehors de FirstOrDefault (remplacer tostring par firstordefault, comment l'exécution de la requête est différente entre votre code et le mien? J'ai essayé votre morceau de code, il courait beaucoup plus vite – jbagavathi

+0

Parce que je commence par obtenir juste le compte que vous voulez, puis le client.Votre exemple de requête d'origine s'exécute comme l'équivalent d'une jointure externe complète ... De même, dans votre exemple de boucle, vous avez oublié de sortir de la boucle externe, donc même après avoir affecté customerName, il continuera à boucler tous les comptes. – KristoferA

+0

Merci, ça l'explique – jbagavathi

1

La quatrième exécution semble avoir atteint la récupération de place du côté Linq. A part cela, LINQ ne sait pas que vous essayez seulement d'obtenir une seule instance du nom du client. Il ne connaît pas la relation que CustomId ou AccountIds sont uniques, ce que suppose votre code. En bref, le code est analogue :)

En outre, dans le premier exemple, vous pourriez vouloir vérifier dans la boucle externe si custerName = NULL de sorte que vous pouvez arrêter avant;)

0

Avez-vous identifié votre utilisation de LINQ comme goulot d'étranglement dans votre application? Si ce n'est pas le cas, il est peu probable que vous le fassiez et la poursuite des microsecondes entre les foreach traditionnels et les lambdas brûle votre temps précieux sans réel bénéfice. Vous passerez probablement plus de temps sur un appel de base de données ou une opération d'E/S que sur toutes les expressions LINQ combinées. Inquiet à propos de ceux-ci à la place.

1

Une chose évidente, regardant le code ci-dessus est - En cas de foreach, vous arrêtez l'exécution de la boucle intérieure lorsque une correspondance est trouvée pour le customerID.

Considérant que, il ne semble pas être le cas avec LINQ.

La sortie de foreach et la requête LINQ sont-elles identiques?
Que diriez-vous d'utiliser un JOIN et d'utiliser FirstOrDefault, comme quelqu'un l'a suggéré ici?

Questions connexes