2015-03-18 2 views
4

У меня есть список фильтров, и я хочу использовать его для запроса к таблице, где возвращаемые элементы содержат ВСЕ значения не только 1.где содержит LINQ все элементы в списке

Например, у меня есть ярлык/тегов. Я хочу вернуть записи, в которых есть теги «спорт» и «футбол». Однако «спорт» и «футбол» хранятся в списке и могут быть любыми другими тегами, которые пользователь поставляет.

Я использую структуру сущности. У меня есть таблица тегов, команд, TeamTags. Мой текущий запрос как таковой:

string _tags = "sport,football"; 
List<string> tags = _tags.Split(',').ToList(); 

var teams = (from t in db.Tags where tags.Contains(t.TagName) select t.Teams).FirstOrDefault().Select(i => i.TeamNames).ToList() 

Но это вернет все команды, которые имеют «спортивный» тег не те, которые помечены как «спорт» и «футбол» только.

Если вы намереваетесь набрав тег «спорт», сначала получите список команд из всех видов спорта. Затем вы добавляете тег «футбол», который будет отфильтрован еще больше для футбольных команд. Поэтому мой код выше в основном делает OR в том месте. Я тоже хочу иметь возможность делать И.

Так пример данные в базе данных будут:

мустанги имеют спортивные и футбольные тег Mets имеет спорт и бейсбол теги

Я хочу, чтобы команда, которая имеет спортивные и футбольные тег, а не спорт или футбол теги ,

+1

You'r e используя отношение из «Тэгов» в «Команды» в вашем коде. Есть ли способ перейти от «Команды» к их «Тэгам»? – JLRishe

+0

Почему вы не используете 'SelectMany' и не создаете проекцию для' Contains' на эти значения? – Greg

+0

@Greg, потому что я никогда не использовал SelectMany или не знаю, о чем вы говорите, когда говорите «произвести проекцию». – user441521

ответ

8

Я предложил бы дать это попробовать:

var teams = (from team in db.Teams 
      where tags.All(tag => team.Tags.Any(ttag => ttag.TagName == tag)) 
      select team).ToList(); 

От там, если вы хотите получить список имен, вы можете сделать (трудно понять, как настроены ваши структуры данных, но что-то вроде этого):

var teamNames = teams.Select(t => t.Name).ToList(); 
+0

Это сделало. Теперь я должен попробовать и понять это :) – user441521

+0

@ user441521 Вы можете просто прочитать его изнутри: 'team.Tags.Any (ttag => ttag.TagName == tag)' будет true, если _any_ тегов команды имеют значение 'tag'. 'tags.All (tag => (этот бит, который я только что объяснил)' будет true, если это верно для _all_ элементов в 'tags'. – JLRishe

0
string _tags = "sport,football"; 
List<string> tags = _tags.Split(',').ToList(); 

var teams = (from t in db.Tags where tags.All(x=> x.Contains(t.TagName)) select t.Teams).FirstOrDefault().Select(i => i.TeamNames).ToList(); 

Это поможет получить вам желаемый результат

+1

Сначала я думаю, что вы имели в виду 'tags.All (x => t.TagName.Contains (x))'. В противном случае вы говорите, что «спорт» и «футбол» содержат подстроку, равную «TagName». Во-вторых, это исправление предполагает, что «TagName» - это что-то вроде «спорт, футбол», но я считаю, что в таблице тегов для спорта и футбола есть отдельные записи, которые ссылаются на одну или несколько команд. – juharr

+0

у вас могут возникнуть проблемы при преобразовании в sql (поскольку вы используете EF). вы можете столкнуться с проблемой N + 1. Просто будьте осторожны. Сколько команд и тегов у вас есть, может иметь большое значение. Если все в памяти и у вас есть много тэгов, которые вы ищете (переменная 'tags'), может быть целесообразно преобразовать ее из списка в HashSet (обрезание, вероятно, около 5 тегов). – viggity

Смежные вопросы