LINQ to SQL其中集合包含集合

时间:2011-06-09 19:55:14

标签: c# sql-server-2008 linq-to-sql

我有一个问题:(我通过映射表(3)在两个表(1和2)之间有很多表:

(1)Trees / (2)Insects 

TreeID <- (3)TreeInsects -> InsectID   

然后是一对多的关系:

Trees.ID -> Leaves.TreeID

我想执行一个查询,它将为我提供昆虫收集的所有叶子(通过树木 - 昆虫映射表)。

E.g。我有List<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 个答案:

答案 0 :(得分:2)

(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 :(得分:1)

我的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 ) );

答案 2 :(得分:0)

尝试调查SelectMany方法 - 我认为这可能是您需要的关键。

我会得到一个可用于该昆虫的树木列表,然后将SelectMany钉在最后,并拉出与该树相关的树叶集合。

答案 3 :(得分:0)

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将很乐意生成一个包含更多昆虫ID的查询,但是当您尝试运行它时,您将获得一个sql异常。要解决此问题,请在较小批次的ID上多次运行查询。

答案 4 :(得分:0)

你如何获得这份昆虫清单?这也是一个查询吗?

无论如何,如果你不介意性能(如果你有一个大数据库,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);