Альтернативная реализация для foreach с использованием выражения 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; }
}
</keywordsearch>

Как я могу построить массив ключевых слов на основе ALL macthing KeywordSearch?

У меня есть этот очень грязный код:

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);
 }
 }
</int></int>

У меня был этот, но он возвращает ЛЮБОЕ соответствующее ключевое слово:

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 ответа

То, что вы концептуально делаете, - это объединение двух коллекций.

Каждый раз, когда вы находите все предметы из одной коллекции, которые обрабатывают текущий элемент цикла foreach вы должны заглянуть в соединение, так как это, вероятно, то, что вы делаете.

A Join не только намного чище, но и намного эффективнее:

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 important to materialize the query now


Вот способ сделать это; он работает с 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. Я думал, что имеет смысл структурировать запрос таким образом.

licensed under cc by-sa 3.0 with attribution.