Выборка элементов, у которых есть определенный набор дочерних элементов (расширенный запрос - возможно?) - PullRequest
2 голосов
/ 30 октября 2008

У меня есть база данных SQL (SQL Server 2008), которая содержит следующий дизайн

ITEM

  • ID (Int, Identity)
  • Имя (NVarChar (50))
  • Описание (NVarChar (200))

META

  • ID (Int, Identity)
  • Имя (NVarChar (50))

Существует отношение N-N между этими двумя, то есть Элемент может содержать ноль или более мета-ссылок, а мета может быть связана с более чем одним элементом. Каждая мета может быть связана с одним и тем же элементом только один раз. Это значит, что у меня классический стол посередине

ITEMMETA

  • ItemID (Int)
  • MetaID (Int)

Я хотел бы выполнить запрос LinqToSql для извлечения всех сущностей элементов, которые содержат определенный набор мета-ссылок. Например, дайте мне все Предметы, с которыми связаны следующие метаэлементы

  • Car
  • Форд
  • Offroad

Можно ли написать такой запрос с помощью LinqToSql? Позвольте мне предоставить еще несколько требований

  • У меня будет список мета-тегов, которые я хочу использовать для фильтрации элементов, которые будут возвращены (например, в приведенном выше примере у меня были Car, Ford и Offroad)
  • Элемент может иметь больше мета-элементов, связанных с ним, чем то, что я предоставляю в матче, т. Е. Если с элементом ассоциированы элементы Car, Ford, Offroad и Red, то предоставление любой их комбинации в фильтре должно привести к совпадению
  • Однако ВСЕ мета-имена, которые предоставляются в фильтре, ДОЛЖНЫ быть связаны с элементом, который будет возвращен в наборе результатов. Таким образом, отправка в автомобилях, Ford, Offroad и Red НЕ ДОЛЖНА совпадать с элементом, у которого ассоциированы Car, Ford и Offroad (без Red)

Я надеюсь, ясно, чего я пытаюсь достичь, я чувствую, что я не так ясен, как я надеялся = / Будем надеяться, этого достаточно:)

Спасибо!

Ответы [ 3 ]

2 голосов
/ 31 октября 2008

Это должно работать для вас:

string[] criteria = new[] { "Car", "Ford", "Offroad" };

var items = 
    from i in db.Item
    let wantedMetas = db.Meta.Where(m => criteria.Contains(m.Name))
    let metas = i.ItemMeta.Select(im => im.Meta)
    where wantedMetas.All(m => metas.Contains(m))
    select i;

По сути, он сравнивает "требуемые" метаты с мета-метрами каждого элемента и выбирает элементы, которые имеют все требуемые мета (или более).

1 голос
/ 31 октября 2008

Вы можете фильтровать элементы, считая отфильтрованные метасы.

List<string> metaList = new List<string>() { "Car", "Ford", "Offroad" };
int metaListCount = metaList.Count;
List<Item> result =
  db.Items
  .Where(i => metaListCount ==
    i.ItemMeta.Meta
    .Where(m => metaList.Contains(m.Name))
    .Count()
  )
  .ToList();

Имейте в виду, что существует верхний предел для этой коллекции в памяти. Содержит ограничение параметра SqlServer (это ~ 200 или ~ 2000, я никогда не смогу вспомнить).

1 голос
/ 31 октября 2008

это возвращает все, что соответствует любому из мета-критериев, а затем отфильтровывает все, что соответствует всем критериям. (также имейте в виду, что ваши отношения должны быть определены в текстовом тексте). Дайте нам знать, если вам нужны разъяснения.

var db = new YourDataContext();
var possibleItems = (from m in db.Metas where <meta criteria> select m.ItemMetas.Item);

var items = possibleItems.GroupBy(y=>y).Where(x=>x.Count() == criteriaCount).Select(x=>x.Key);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...