2011-06-06 43 views
35

在C#中编写LINQ查询时,我知道我可以使用join关键字执行加入。但是下面是做什么的?LINQ加入多个子句

from c in Companies 
from e in c.Employees 
select e; 

一个LINQ本书中,我说这是一个连接类型,但不正确的连接(使用join关键字)。那么到底是什么类型的连接呢?

+1

Linq-to-Objects,-Sql,-Entities?在-Objects中,这不是一个连接,而是一个'SelectMany'操作。在其他情况下,可以根据数据将其翻译为左侧或内侧。 – 2011-06-06 19:42:23

+0

@Anthony:我还没有用过那么多的LINQ。所以我的问题只是一般而已,并不局限于任何特定的提供者。但是,最终,我最终可能会使用LINQ to Entities。 – 2011-06-06 20:25:17

回答

39

多个“from”语句被视为复合linq语句。它们就像嵌套的foreach语句。 MSDN的页面确实列出一个很好的例子here

var scoreQuery = from student in students 
         from score in student.Scores 
          where score > 90 
          select new { Last = student.LastName, score }; 

这个声明可以改写为:

SomeDupCollection<string, decimal> nameScore = new SomeDupCollection<string, float>(); 
foreach(Student curStudent in students) 
{ 
    foreach(Score curScore in curStudent.scores) 
    { 
     if (curScore > 90) 
     { 
     nameScore.Add(curStudent.LastName, curScore); 
     } 
    } 
} 
24

这将被翻译成SelectMany()调用。它本质上是一个交叉连接。

Jon Skeet在他的博客上谈到这个问题,作为Edulinq series的一部分。 (向下滚动至次要“从”条款。)

-1

所有第一组对象将与所有第二组对象连接。例如,以下测试将通过...

[TestMethod()] 
    public void TestJoin() 
    { 
     var list1 = new List<Object1>(); 
     var list2 = new List<Object2>(); 

     list1.Add(new Object1 { Prop1 = 1, Prop2 = "2" }); 
     list1.Add(new Object1 { Prop1 = 4, Prop2 = "2av" }); 
     list1.Add(new Object1 { Prop1 = 5, Prop2 = "2gks" }); 

     list2.Add(new Object2 { Prop1 = 3, Prop2 = "wq" }); 
     list2.Add(new Object2 { Prop1 = 9, Prop2 = "sdf" }); 

     var list = (from l1 in list1 
        from l2 in list2 
        select l1).ToList(); 

     Assert.AreEqual(6, list.Count); 

    } 
+1

这与问题中的代码不同。你正在展示一个笛卡尔产品,这不是这个。 – 2011-06-06 19:48:36

16

你列出的代码:

from c in company 
from e in c.Employees 
select e; 

...会产生一个列表在company变量中的每个公司的每个员工的总数。如果员工为两家公司工作,他们将被列入清单两次。

这里可能发生的唯一“加入”是当您说c.Employees时。在SQL支持的提供程序中,这将转换为从Company表到Employee表的内部联接。

然而,双from结构通常用于执行“加入”手动,像这样:

from c in companies 
from e in employees 
where c.CompanyId == e.CompanyId 
select e; 

这将产生类似的效果,你发布的代码,以根据潜在细微的差别是什么包含employees变量。这也将是等效于下面的join

from c in companies 
join e in employees 
    on c.CompanyId equals e.CompanyId 
select e; 

如果你想要一个笛卡尔乘积,但是,你可以只取出where条款。 (使它值得任何东西,你可能会想改变select咯,太,虽然)。

from c in companies 
from e in employees 
select new {c, e}; 

这最后一个查询会给你的公司和员工的每一个可能的组合。