2010-12-14 77 views
1

J'ai écrit le code suivant:déclarations Linq ont besoin d'optimiser

//get the user from the DB 
var tmpuser = _db.aspnet_Users.First(q => q.UserName == user.Identity.Name); 

//list the direct connections to Verbond 
List<Verbond> verb1 = tmpuser.UsersVerbondens 
          .Where(q => q.Schooljaar.Sch_Schooljaar == schooljaarparam) 
          .Select(q => q.Verbond) 
          .ToList(); 

//list the connected Facturatieverbonden 
List<FacturatieVerbonden> verb2 = tmpuser.UsersFacturatieVerbondens 
             .Where(q => q.Schooljaar.Sch_Schooljaar == schooljaarparam) 
             .Select(q => q.FacturatieVerbonden) 
             .ToList(); 

//loop through the facturatieverbonden and add their verbonds to the first list 
foreach (FacturatieVerbonden v in verb2) { 
    verb1.AddRange(v.Verbonds); 
} 

//make a distinct list 
List<Verbond> test = verb1.Distinct().ToList(); 

Ainsi, les utilisateurs peuvent être connectés à 0 ou plus facturatieverbonden et peut également être connecté à verbond. Un facturatieverbonden peut avoir un ou plusieurs verbond sous lui-même.

Ce dont j'ai besoin est une liste de tous les verbond auxquels l'utilisateur est connecté, directement ou indirectement via le facturatieverbonden.

Mon code fonctionne mais je ne pense pas que ce soit très efficace. Des conseils pour le rendre plus propre?

Répondre

5

Votre requête n'est pas très LINQy. Voici une amélioration potentielle:

  //list the direct connections to Verbond 
var test = (from q in tmpuser.UsersVerbondens 
      where q.Schooljaar.Sch_Schooljaar == schooljaarparam 
      select q.Verbond) 
      //return distinct values 
      .Union 
      //list the connected Facturatieverbonden 
      (from q in tmpuser.UsersFacturatieVerbondens 
      where q.Schooljaar.Sch_Schooljaar == schooljaarparam 
      from v in q.FacturatieVerbonden.Verbonds 
      select v) 
      //return a List 
      .ToList(); 

En faisant ToList la dernière chose qu'il fait, le calcul entier peut être fait dans la base de données, en évitant toutes les listes intermédiaires.

+0

Bonne idée mais petit problème: q.Verbond et vf.Verbonds (pluriel) sont de types différents. –

+0

David B: C'est le problème avec la programmation dans une langue étrangère - il est difficile de dire quand quelque chose n'a pas de sens. Est-ce que je l'ai maintenant? – Gabe

+0

fonctionne génial !!! :) – Stefanvds

0

Votre problème de performance est ici. Chaque appel AddRange énumérera v.Verbonds, et chacun sera un aller-retour de base de données.

//loop through the facturatieverbonden and add their verbonds to the first list 
foreach (FacturatieVerbonden v in verb2) { 
    verb1.AddRange(v.Verbonds); 
} 

Pour résoudre ce problème:

//query the connected Facturatieverbonden 
IQueryable<FacturatieVerbonden> verbQuery2 = tmpuser.UsersFacturatieVerbondens 
    .Where(q => q.Schooljaar.Sch_Schooljaar == schooljaarparam) 
    .Select(q => q.FacturatieVerbonden); 

verb1.AddRange(verbQuery2.SelectMany(fv => fv.Verbonds)); 

Il y a encore beaucoup de place pour serrer la performance, mais au moins cette adresse le problème brut. Vous pourriez facilement observer une accélération de 10 fois.