这个LINQ的方法语法是什么,它是一个连接,如果没有那么它是什么?

时间:2014-11-25 14:15:34

标签: linq

我发现自己在LINQ中使用了这种模式:

    class Thing
    {
        public int ID { get; set; }
        public int ColorID { get; set; }
    }
    class Color
    {
        public int ID { get; set; }
        public string Description { get; set; }
    }
    static void Main()
    {
        var things = new List<Thing> { new Thing { ID = 1, ColorID = 1 }, new Thing { ID = 2, ColorID = 1 }, new Thing { ID = 3, ColorID = 2 }, new Thing { ID = 4, ColorID = 1 } };
        var colors = new List<Color> { new Color { ID = 1, Description = "red" }, new Color { ID = 2, Description = "green" }, new Color { ID = 3, Description = "blue" } };
        var joined = (from thing in things
                      from color in colors
                      where thing.ColorID == color.ID
                      select new { ID = thing.ID, Color = color.Description }).ToArray();
        foreach (var thing in joined)
        {
            Console.WriteLine("(" + thing.ID + ", " + thing.Color + ")");
        }
        //Writes:
        //(1, red)
        //(2, red)
        //(3, green
        //(4, red)
    }

它的核心,四行查询语法,感觉非常像我可能在tSQL中编写的INNER JOIN,但当我查看examples of LINQ query syntax for joins时,他们使用join这个词,而上面的LINQ没有。

上面的LINQ正在执行的'join'是什么?如何在LINQ方法语法中重写它?

1 个答案:

答案 0 :(得分:3)

就LINQ理解而言,它根本没有执行连接。它只是基于两个属性进行过滤,其中一个发生来自一个范围变量而另一个发生来自另一个。在方法语法中,您将其写为:

var joined = things.SelectMany(thing => colors,
                               (thing, color) => new { thing, color })
                   .Where(pair => pair.thing.ColorID == pair.color.ID)
                   .Select(pair => new { ID = pair.thing.ID,
                                         Color = pair.color.Description })
                   .ToArray();

此处pair由编译器有效地自动引入为透明标识符。这不是由于where中的过滤,而是由于有多个from子句...在第一个使用from之后的每个SelectMany子句,并引入了一个透明的标识符,允许您引用多个范围变量(thingcolor),这些变量组成一个单独的对象,这样管道的每个阶段只能理论上处理一个值。

请注意,当您有两个from条款时:

from person in people
from book in books

...... 行为就像笛卡尔联接......但LINQ允许更精细的东西,例如:

from person in people
from book in person.Books

换句话说,第二个序列可以取决于&#34;当前&#34;来自第一个序列的值。管道的任何后续阶段(例如,whereselect)作用于每对:第一个序列中的一个,然后是第一个序列中的元素生成的第二个序列中的一个。