LINQ to SQL, где коллекция содержит коллекцию - PullRequest
6 голосов
/ 09 июня 2011

У меня проблема :( У меня есть таблица много-много между двумя таблицами (1 и 2) через таблицу сопоставления (3):

(1)Trees / (2)Insects 

TreeID <- (3)TreeInsects -> InsectID   

А потом отношения один ко многим:

Trees.ID -> Leaves.TreeID

И я хотел бы выполнить запрос, который даст мне все листья для сбора насекомых (через таблицу картирования деревьев-насекомых).

например. У меня есть List<Insects>, и я хочу, чтобы все Листья, которые связаны с любым из Насекомых в Списке через таблицу отображения Tree-Insects.

Это кажется простой задачей, но по какой-то причине у меня возникают проблемы с этим !!

Лучшее, что у меня есть: но Single () делает его неверным:

   from l in Leaves
            where (from i in Insects
                   select i.ID)
                  .Contains((from ti in l.Tree.TreeInsects
                             select ti.InsectID).Single())
            select l;

Ответы [ 5 ]

2 голосов
/ 10 июня 2011
(from i in insectsCollection
select from l in Leaves
       let treeInsectIDs = l.Tree.TreeInsects.Select(ti => ti.InsectID)
       where treeInsectIDs.Contains(i.ID)
       select l)
.SelectMany(l => l)
.Distinct();
1 голос
/ 10 июня 2011

Я плохо с sql-подобным синтаксисом, поэтому я буду писать с расширениями.

ctx.Leaves.Where(l => ctx.TreeInsects.Where( ti => list_with_insects.Select(lwi => lwi.InsectID).Contains( ti.InsectID ) ).Any( ti => ti.TreeID == l.TreeID ) );
0 голосов
/ 10 июня 2011

Как вы получили этот список насекомых?Это тоже запрос?

В любом случае, если вы не против производительности (SelectMany может работать медленно, если у вас большая база данных), это должно сработать:

List<Insect> insects = .... ; //(your query/method)

IEnumerable<Leave> leaves = db.TreeInsects
    .Where(p=> insects.Contains(p.Insect))
    .Select(p=>p.Tree)
    .SelectMany(p=>p.Leaves);
0 голосов
/ 10 июня 2011
List<int> insectIds = localInsects.Select(i => i.ID).ToList();

  //note - each leaf is evaluated, so no duplicates.
IQueryable<Leaf> query =
  from leaf in myDataContext.Leaves
  where leaf.Tree.TreeInsects.Any(ti => insectIds.Contains(ti.InsectId))
  select leaf;


  //note, each matching insect is found, then turned into a collection of leaves.
  // if two insects have the same leaf, that leaf will be duplicated.
IQueryable<Leaf> query2 =
  from insect in myDataContext.Insects
  where insectIds.Contains(insect.ID)
  from ti in insect.TreeInsects
  from leaf in ti.Tree.Leaves
  select leaf;

Также обратите внимание, что Sql Server имеет ограничение параметра ~ 2100.LinqToSql с радостью сгенерирует запрос с большим количеством идентификаторов насекомых, но при попытке его запустить вы получите исключение sql.Чтобы решить эту проблему, выполните запрос более одного раза для небольших пакетов идентификаторов.

0 голосов
/ 10 июня 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...