使用lambda表达式和linq

时间:2010-05-19 16:21:20

标签: c# linq soap lambda jira

所以我刚开始使用linq以及使用lambda表达式。在尝试获取我想要的数据时,我遇到了一个小小的打嗝。此方法应返回从Jira

打开或正在进行的所有项目的列表

这是代码

    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();
    }

现在这只选择“开放”的问题,似乎跳过“正在进行中”的问题。

我的问题:首先,为什么我只得到“公开”问题,第二,有更好的方法吗?

我首先获得所有状态的原因是该问题仅存储该状态ID,因此我获得所有状态,获得与“打开”和“进行中”匹配的ID,然后将这些ID号匹配到问题状态字段。

6 个答案:

答案 0 :(得分:3)

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

您所拥有的代码只检查第一个状态并返回false。您需要迭代所有状态,并且只有在它根本不在列表中时才返回false。

答案 1 :(得分:2)

好吧,你可以改变

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));

至于为什么你没有得到这两种状态 - 斯蒂芬已经回答了这个问题。我上面的代码更改也将解决这个问题。

答案 2 :(得分:1)

您只获得一个状态的原因是您在第一次检查后总是退出循环。如果第一个项目不匹配,则不再检查项目。如果你在else中删除了返回,它将起作用:

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

您应确保实现所需状态的集合,以便每次使用时都不会重新运行创建它的查询:

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

如果您只想检查几种状态,则无需提高效率。如果有很多状态,您可以将状态识别为HashSet并使用它的Contains方法,这比循环遍历项目快得多。

答案 3 :(得分:0)

代码对我来说是正确的,尽管有很多方法可以用较少的代码编写代码......

关于:

  

现在这只选择“开放”的问题,似乎跳过“正在进行中”的问题。

你能否确认两者都在所需的状态?

另外我假设RemoteIssue.status属性确实是指状态的id而不是name,因为那是你要比较它的东西?

然后对于代码,根据Martin Harris的回答:我会使用Contains运算符而不是你的内循环......

答案 4 :(得分:0)

改变这个:

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=>
            {
                foreach (var v in desiredStatuses)
                {
                    if (x.status == v)
                        return true;
                    //else
                        //return false;
                }
                return false;
            });

答案 5 :(得分:0)

其他答案是正确的,但你可以用直接的Lambda而不是匿名代表更简洁地做到这一点。

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

所以你的整个方法看起来像:

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();
}

这基本上发出了SQL“IN”子句的等价物。所以你的陈述是:

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