首页 > 解决方案 > Linq Join does not seem to have data of the complete join

问题描述

I modified this code (below gray section), and original is at https://www.youtube.com/watch?v=gwD9awr3NNo

Its kind of complicated.

The question is regarding this part of the code (complete code below):

var groupJoin =
                    from owner in owners
                    orderby owner.OwnerID
                    join animal in animals on owner.OwnerID
                    equals animal.OwnerID into ownerGroup
                    select new
                    {
                        Owner = owner.Name,
                        Animals = from owner2 in ownerGroup
                              select owner2
                    };

Should ownerGroup not contain both owner and animal information (it is a join, join means it should contain both).

So assuming that is true, what causes Animals to be restricted to only information from animals (not having information from owners)? The way I deduced this is: Intellisense shows x (see below, complete code). to have only information from animal class

SEE LINE: //Console.WriteLine("* {0}", x.Name); <-- DOES NOT WORK

namespace LinqTutorialByDerekBanas
{

    class Program
    {

        static void Main(string[] args)
        {

            bool RunMe;

            QueryAnimalData();
        }

        class Animal
        {
            public string AnimalName { get; set; }
            public double Weight { get; set; }
            public double Height { get; set; }
            public int OwnerID { get; set; }

            public Animal(string name = "No Name",
                double weight = 0,
                double height = 0)
            {
                AnimalName = name;
                Weight = weight;
                Height = height;
            }

            public override string ToString()
            {
                return string.Format("{0} weighs {1}lbs and is {2} inches tall",
                    AnimalName, Weight, Height);
            }
        }


        class Owner
        {
                public string Name { get; set; }
                public int OwnerID { get; set; }
        }

            static void QueryAnimalData()
            {
                Animal[] animals = new[]
                {
                    new Animal{AnimalName = "German Shepherd",
                    Height = 25,
                    Weight = 77,
                    OwnerID = 1},
                    new Animal{AnimalName = "Chihuahua",
                    Height = 7,
                    Weight = 4.4,
                    OwnerID = 2},
                    new Animal{AnimalName = "Saint Bernard",
                    Height = 30,
                    Weight = 200,
                    OwnerID = 3},
                    new Animal{AnimalName = "Pug",
                    Height = 12,
                    Weight = 16,
                    OwnerID = 1},
                    new Animal{AnimalName = "Beagle",
                    Height = 15,
                    Weight = 23,
                    OwnerID = 2}
                };

                Owner[] owners = new[]
                {
                    new Owner{Name = "Doug Parks",
                    OwnerID = 1},
                    new Owner{Name = "Sally Smith",
                    OwnerID = 2},
                    new Owner{Name = "Paul Brooks",
                    OwnerID = 3}
                };



                // Create a group inner join
                // Get all animals and put them in a
                // newly created owner group if their
                // IDs match the owners ID 
                var groupJoin =
                    from owner in owners
                    orderby owner.OwnerID
                    join animal in animals on owner.OwnerID
                    equals animal.OwnerID into ownerGroup
                    select new
                    {
                        Owner = owner.Name,
                        Animals = from owner2 in ownerGroup
                                  select owner2
                    };

                int totalAnimals = 0;

                foreach (var ownerGroup in groupJoin)
                {
                    Console.WriteLine(ownerGroup.Owner);
                    foreach (var x in ownerGroup.Animals)
                    {
                        totalAnimals++;
                        Console.WriteLine("* {0}", x.AnimalName);
                        //Console.WriteLine("* {0}", x.Name);  <-- DOES NOT WORK

                    }
                }
            }

     }
}

标签: c#linq

解决方案


join...into是 a 的查询语法GroupJoin。组连接是一种 LINQ 结构,它将一个项目与一组相关项目相关联(例如,使用 1 到多个外键)。

所以在查询中,ownerGroup(我会命名为animaljoinor aj)是animals与单个所有者相关的集合OwnerID

线

Animals = from owner2 in ownerGroup select owner2

对我来说毫无意义 - 你为什么要重命名owner2 Animals?由于ownerGroup是用词不当,实际上是一组animals,我不确定你在这里的意图。

考虑实际实现组加入的扩展方法(这是Enumerable版本但Queryable类似):

public static IEnumerable<TResult> GroupJoin<TOuter,TInner,TKey,TResult> (
    this IEnumerable<TOuter> outer,
    IEnumerable<TInner> inner,
    Func<TOuter,TKey> outerKeySelector,
    Func<TInner,TKey> innerKeySelector,
    Func<TOuter,IEnumerable<TInner>,TResult> resultSelector);

这使用两个 lambda 组合两个序列 (outerinner) 以提取匹配键,然后为每个outerouter和所有匹配 ( IEnumerable<TInner>) inners 发送到结果 lambda。


推荐阅读