2010-05-19 6 views
0

Je viens donc de commencer à travailler avec linq et à utiliser des expressions lambda. J'ai couru dans un petit hoquet en essayant d'obtenir des données que je veux. Cette méthode doit renvoyer une liste de tous les projets qui sont ouverts ou en cours de JiraUtilisation des expressions lambda et linq

Voici le code

public static List<string> getOpenIssuesListByProject(string _projectName) 
    { 
     JiraSoapServiceService jiraSoapService = new JiraSoapServiceService(); 
     string token = jiraSoapService.login(DEFAULT_UN, DEFAULT_PW); 
     string[] keys = { getProjectKey(_projectName) }; 

     RemoteStatus[] statuses = jiraSoapService.getStatuses(token); 
     var desiredStatuses = statuses.Where(x => x.name == "Open" || x.name == "In Progress") 
      .Select(x=>x.id); 

     RemoteIssue[] AllIssues = jiraSoapService.getIssuesFromTextSearchWithProject(token, keys, "", 99); 
     IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
      { 
       foreach (var v in desiredStatuses) 
       { 
        if (x.status == v) 
         return true; 
        else 
         return false; 
       } 
       return false; 
      }); 
     return openIssues.Select(x => x.key).ToList(); 
    } 

En ce moment, cela ne sélectionnez problèmes qui sont « ouverts », et semble ignorer ceux qui sont "En cours".

Ma question: Premièrement, pourquoi est-ce que je ne reçois que les problèmes «ouverts», et deuxièmement, y a-t-il une meilleure façon de procéder? La raison pour laquelle je reçois tous les statuts en premier est que le problème ne stocke que cet identifiant de statut, donc j'obtiens tous les statuts, obtenons les identifiants qui correspondent à "Ouvrir" et "En cours", puis je fais correspondre ces numéros le champ d'état des problèmes.

Répondre

3
IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
     { 
      foreach (var v in desiredStatuses) 
      { 
       if (x.status == v) 
        return true; 
      } 
      return false; 
     }); 

Le code que vous aviez été seulement vérifier le premier état et le retour faux. Vous devez répéter tous les états et renvoyer les faux uniquement si ce n'est pas du tout dans la liste.

+0

, tout compris cela moi-même aussi. Je l'ai regardé pendant 45 minutes, et 2 minutes après que je demande de l'aide je le découvre :) – Andy

2

Eh bien, vous pouvez changer

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
{ 
    foreach (var v in desiredStatuses) 
    { 
     if (x.status == v) 
      return true; 
     else 
      return false; 
    } 
    return false; 
}); 

à

IEnumerable<RemoteIssue> openIssues = 
     AllIssues.Where(x=> desiredStatuses.Contains(x.status)); 

Quant à savoir pourquoi vous ne recevez pas les statuts - Stephan a répondu. Mon changement de code ci-dessus va résoudre ce problème aussi.

+0

Merci pour la ligne abrégée code :) Merci – Andy

1

La raison pour laquelle vous n'obtenez qu'un seul statut, c'est que vous revenez toujours hors de la boucle après la première vérification. Si le premier élément ne correspond pas, aucun élément n'est vérifié. Si vous supprimez le retour dans l'autre, il fonctionnera:

foreach (var v in desiredStatuses) { 
    if (x.status == v) { 
    return true; 
    } 
} 
return false; 

Vous devez vous assurer de réaliser la collecte des statuts souhaités, de sorte que vous ne relancez pas la requête qui crée à chaque fois que vous utilisez :

var desiredStatuses = 
    statuses 
    .Where(x => x.name == "Open" || x.name == "In Progress") 
    .Select(x=>x.id) 
    .ToList(); 

S'il y a seulement quelques états que vous voulez vérifier, il n'y a pas besoin de le rendre plus efficace que cela. S'il y a beaucoup de statuts, vous pouvez réaliser les statuts dans un HashSet et utiliser la méthode Contains qui est beaucoup plus rapide que de boucler les éléments.

+0

Merci pour l'info sur l'ajout de ToList() pour éviter la requête à chaque fois. Je suis toujours novice donc un peu perdu dans ça :) – Andy

0

Le code semble bon pour moi, bien qu'il existe des façons de le faire avec moins de code écrit ...

En ce qui concerne:

En ce moment, cela ne sélectionnez problèmes qui sont « ouverts », et semble ignorer ceux qui sont "en cours".

Pouvez-vous confirmer que les deux sont dans les desiredStatuses bien?

Aussi, je suppose que la propriété RemoteIssue.status fait en effet référence à l'identifiant de l'état plutôt que du nom, puisque c'est ce que vous le comparez?

Ensuite, le code, selon la réponse de Martin Harris: J'utiliser Contains opérateur plutôt que votre boucle intérieure ...

0

Modifier ceci:

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
      { 
       foreach (var v in desiredStatuses) 
       { 
        if (x.status == v) 
         return true; 
        else 
         return false; 
       } 
       return false; 
      }); 

à ceci:

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
      { 
       foreach (var v in desiredStatuses) 
       { 
        if (x.status == v) 
         return true; 
        //else 
         //return false; 
       } 
       return false; 
      }); 
0

Les autres réponses sont correctes, mais vous pouvez le faire un peu plus concis avec un Lambda droit au lieu d'un délégué anonyme.

IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x=> 
     desiredStatuses.Contains(x.status) 

donc votre méthode tout ressemblerait à ceci:

public static List<string> getOpenIssuesListByProject(string _projectName) 
{ 
    JiraSoapServiceService jiraSoapService = new JiraSoapServiceService(); 
    string token = jiraSoapService.login(DEFAULT_UN, DEFAULT_PW); 
    string[] keys = { getProjectKey(_projectName) }; 

    RemoteStatus[] statuses = jiraSoapService.getStatuses(token); 
    var desiredStatuses = statuses.Where(x => x.name == "Open" || x.name == "In Progress") 
     .Select(x=>x.id); 

    RemoteIssue[] AllIssues = jiraSoapService.getIssuesFromTextSearchWithProject(token, keys, "", 99); 
    IEnumerable<RemoteIssue> openIssues = AllIssues.Where(x => desiredStatuses.Contains(x.status)); 
    return openIssues.Select(x => x.key).ToList(); 
} 

Cette émet essentiellement l'équivalent d'un SQL "IN" clause. Donc, votre déclaration se lit comme suit:

SELECT <RemoteIssue> FROM AllIssues AS x WHERE x.status IN <desiredStatuses> 
Questions connexes