2012-02-04 71 views
4

我是新来的LINQ,两种环境下使用时对象,并有一个关于from条款问题:外连接LINQ

1)进行交叉连接,如查询波纹管

var q1 = from person in people 
     from job in jobs 
     select new {person, job} 

2)以执行一个外部联接

var q2 = from person in people 
    join pet in pets on person equals pet.Owner into gj 
    from subpet in gj 
    select new { OwnerName = person.FirstName, PetName = subpet.Name }; 

确实从子句第二充当交叉连接或它取决于上下文中计算的?因为 Q1会产生people.Count * jobs.Count元件 但Q2将产生仅people.Count

回答

3

根据MS文档,使第二查询左外连接,你应该使用DefaultIfEmpty方法看到here。 from子句始终以相同的方式进行评估:它会返回序列中的每个元素,它是预定义的源还是上下文变量。

编辑:我会尝试从一开始来解释。起初你内心加入(群体加入,具体)人和宠物。然后你从结果集合(实际上是person-pets集)中选择新的匿名对象,从gj set元素中获取人名(和gj set元素中的每个宠物)的子名称。我认为第二个来自gj的选择,并且每个人已经是gj集合元素的一部分,所以不会进行交叉连接。如果您在第二个from子句中调用gj.DefaultIfEmpty()方法,则没有任何宠物的人(在gj set元素中有空宠物集合)将被添加到结果集中。你可以阅读下面的文章,以更好地理解它:

+0

对于查询'q1'来说,第二个'from'充当来自人员和来自作业的元素之间的交叉连接,第二个查询的情况如何? – 2012-02-04 13:28:57

+0

在我看来,'from'子句不是作为交叉连接,而是select。 'from'只是进行交叉连接的手段,因为它提供了序列中的元素。在第二个示例中,您将person-pet内部联接生成为gj,并使用第二个“from”从结果集中选择每个元素,仅此而已,没有什么更少的。要执行一个左外连接,你应该为没有宠物的人替换正确的值(来自gj set)。 – 2012-02-04 13:47:06

+0

是否意味着'from'作为foreach循环,而第二个'from'是第一个内部foreach? – 2012-02-04 14:08:42

0

join通常用于基于匹配密钥的两个序列的元素相关,所以它是通常一个内连接,但它取决于你定义的匹配,例如下面会产生交叉联接:

List<int> A = new List<int> { 1, 2, 3, 4, 5 }; 
List<int> B = new List<int> { 1, 2, 3, 4, 5 }; 
var c = (from a in A join b in B on 1 equals 1 select new { a, b }).ToList(); 
+0

我的问题是关于'from'条款(一个Seconde系列中查询)不'join',它是作用在这两个查询相同的方式(Q1和Q2),或者它产生交叉连接的第一个和一个外部连接的第二个? – 2012-02-04 11:33:49

0

基于上下文进行评估。如果不是,您将无法使用上下文变量,如gj。但是,如果您不使用该上下文,就像在第一个查询中那样,它的行为与交叉连接相同。

你说的第二个查询为您提供了元素的意外数字。也许你不应该把注意力集中在那个上面,而是要看你得到了什么元素,以及这与你所期待的有什么不同。

+0

对于查询'q1'来说,第二个'from'是来自人员和来自作业的元素之间的交叉连接,第二个查询的情况如何? – 2012-02-04 13:37:29