使用linq表达式对foreach的替代实现

时间:2013-12-04 19:25:17

标签: c# asp.net-mvc linq

我有一系列关键字:splitKeywords = {“KeywordA”,“KeywordB”,“KeywordC”}

实体KeywordSearch:

public class KeywordSearch
{
    // Primary properties
    public int Id { get; set; }
    public string Name { get; set; }

    // Navigation properties
    public Keyword Keyword { get; set; }
}

关键字的位置是:

public class Keyword
{
    // Primary properties
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<KeywordSearch> KeywordSearches { get; set; }
}

如何基于所有macthing KeywordSearch构建KeywordIds数组?

我有这个非常丑陋的代码:

var keywordSearchQuery = _keywordSearchRepository.Query;

List<int> keywordIds = new List<int>();

foreach (var keyword in splitKeywords)
{
    var keywordsFound = keywordSearchQuery.Where(kws => kws.Name == keyword).Select(kws => kws.Keyword.Id);

    if (keywordsFound.Count() == 0)
    {
        keywordIds.Clear();
        return null;
    }
    else
    {
        keywordIds.AddRange(keywordsFound);
    }
 }

我有这个,但它会返回任何匹配的关键字:

keywordIds = keywordSearchQuery.Where(ks => splitKeywords.Contains(ks.Name)).Select(ks => ks.Keyword.Id);

编辑:

示例:

KeywordSearch = { 1, "KEYWORDA", { 1, "KeywordA" }}, 
                { 2, "KEYWORDB", { 2, "KeywordB" }},
                { 3, "KEYWORDC", {3, "KeywordC" }}

 If I search for "KEYWORDA", I get KeywordId = 1
 If I search for "KEYWORDA KEYWORDB", I get KeywordId = 1,2
 If I search for "KEYWORDA KEYWORDX", I get NULL

2 个答案:

答案 0 :(得分:1)

您在概念上正在做的是加入这两个系列。

任何时候你发现一个集合中的所有项目都是foreach循环的当前项目,你应该查看一个联接,因为这可能就是你正在做的事情。

加入不仅更清洁,而且效率更高:

var query = from keywordSearch _keywordSearchRepository.Query
    join keyword in splitKeywords
    on keywordSearch.Name equals keyword
    select keywordSearch.Keyword.Id;

return query; //add a ToList here if it's important to materialize the query now

答案 1 :(得分:0)

这是一种方法;它适用于LINQ to Objects,我不确定在通过EF查询时它是如何工作的。

var keywordIds = from keyword in _keywordRepository
where splitKeywords.Intersect(keyword.KeywordSearches.Select(kws => kws.Name))
                   .Count() == splitKeywords.Count
select keyword.Id;

请注意,此查询基于_keywordRepository而非_keywordSearchRepository。我认为以这种方式构造查询更有意义。