我们是否需要LINQ中的外连接的join子句?

时间:2015-01-21 23:58:23

标签: c# .net linq

This MSDN page给出了以下外连接示例:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public Person Owner { get; set; }
}

public static void LeftOuterJoinExample()
{
    Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
    Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
    Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
    Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

    // Create two lists.
    List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

    var query = from person in people
                join pet in pets on person equals pet.Owner into gj
                from subpet in gj.DefaultIfEmpty()
                select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) };

    foreach (var v in query)
    {
        Console.WriteLine("{0,-15}{1}", v.FirstName + ":", v.PetName);
    }
}

// This code produces the following output: 
// 
// Magnus:         Daisy 
// Terry:          Barley 
// Terry:          Boots 
// Terry:          Blue Moon 
// Charlotte:      Whiskers 
// Arlene:

join关键字有什么意义?以下查询具有相同的结果。

var query2 = from person in people
             from pet in pets.Where (p => p.Owner.Equals(person)).DefaultIfEmpty()
             select new { person.FirstName, PetName = (pet == null ? String.Empty : pet.Name) };

这两个在功能上是否相同?如果没有,它们有何不同?如果是,使用join关键字进行外连接有什么好处?看起来像是一种写出“&#39;哪里”的奇特方式。条款。但也许还有其他背景,它真的有用吗?

注意:我意识到很可能join子句也用于内连接,组连接等,我想了解是否有理由将它用于外连接。

2 个答案:

答案 0 :(得分:3)

在Linq-to-Objects中,它们将编译为不同的查询,并且可能具有显着不同的性能。

join运算符将在内部为&#34;右手&#34;创建Lookup。设置将使得更快地检索匹配结果,因为它通过哈希码组织项目。

使用Where子句将按以下方式执行查找(粗略的伪代码,而不是确切的实现):

foreach(var left in leftSet)
{
   foreach(var right in rightSet)
   {
      if(left.key equals right.key)
          yields return result
   }
}

对于左集合中的每个对象,您都要对正确的集合进行全面扫描,以找到&#34;匹配&#34;对象。对于大型集合,性能影响可能非常显着。

请注意,Where方法可以做&#34;加入&#34;由于join仅支持等连接,因此join无法实现这一点。

使用Ling-to-SQL,Linq-to-EF等,差异很大程度上取决于底层查询提供程序。你可以通过交叉连接/使用左连接获得类似的性能,但是你必须尝试并测量以确定。

答案 1 :(得分:1)

你也没有用于内部联接,但在许多情况下,在&#34;其中&#34;条款效率较低。当对具有外键索引而不是简单对象集合的表执行此操作时,这一点就变得更加明显。

我知道你的问题是关于LINQ的,但由于其中许多概念都来自SQL,所以值得一提的是:从历史上看,SQL的某些方言根本没有连接子句 - 你会用逗号列出表,并在where子句中执行所有逻辑,在Oracle表上使用特定于供应商的语法[(+),在MS SQL上使用左侧/右侧连接*==*等]表示外部联接。