简体   繁体   English

C#Linq Inner Join

[英]C# Linq Inner Join

I want to select the persons only who are having pets. 我想选择只有宠物的人。

when I execute the query 当我执行查询

var query = from p in people
                        join
                        pts in pets
                        on p equals pts.Owner into grp
                        select new {grp=grp,PersonName=p.FirstName};

Person does not have pet also get selected. 没有宠物的人也会被选中。

My Lists are 我的名单是

Person[] prn = new Person[3];
prn[0] = new Person();
prn[0].FirstName = "Jon";
prn[0].LastName = "Skeet";

prn[1] = new Person();
prn[1].FirstName = "Marc";
prn[1].LastName = "Gravell";

prn[2] = new Person();
prn[2].FirstName = "Alex";
prn[2].LastName = "Grover";

List<Person> people = new List<Person>();

 foreach (Person p in prn)
 {
     people.Add(p);
 }

 Pet[] pt = new Pet[3];

 pt[0] = new Pet();
 pt[0].Name = "Zonny";
 pt[0].Owner = people[0];

pt[1] = new Pet();
pt[1].Name = "Duggie";
pt[1].Owner = people[0];

pt[2] = new Pet();
pt[2].Name = "Zoggie";
pt[2].Owner = people[1];

List<Pet> pets=new List<Pet>();
 foreach(Pet p in pt)
 {
    pets.Add(p);
 }

That's because you're using join ... into which does a group join. 那是因为你正在使用join ... into群组加入。 You just want a normal join: 你只想要一个普通的连接:

var query = (from p in people
             join pts in pets on p equals pts.Owner
             select p).Distinct();

Alternatively, if you want the people with pets, and their owners, you could do something like: 或者,如果您想要有宠物的人及其主人,您可以做以下事情:

var query = pets.GroupBy(pet => pet.Owner)
                .Select(x => new { Owner = x.Key, Pets = x.ToList() });

That will give a result where you can get each owner and their pets, but only for people who have pets. 这将产生一个结果,你可以得到每个主人和他们的宠物,但只有宠物的人。

If you want something else, let us know... 如果你想要别的东西,请告诉我们......

By the way, now would be a good time to learn about object and collection initializers. 顺便说一下,现在是了解对象和集合初始化器的好时机。 Here's a simpler way to initialize your people list, for example: 这是一种初始化people列表的简单方法,例如:

List<Person> people = new List<Person>
{
    new Person { FirstName = "Jon", LastName = "Skeet" },
    new Person { FirstName = "Marc", LastName = "Gravell" },
    new Person { FirstName = "Alex", LastName = "Grover" },
};

Much more compact :) 更紧凑:)

EDIT: A cross join is easy: 编辑:交叉连接很简单:

var query = from person in people
            from pet in pets
            select new { person, pet };

Left joins are effectively emulated using group joins. 使用组连接有效地模拟左连接。 As it sounds like you've got C# in Depth, I suggest you read chapter 11 thoroughly :) 听起来你有深度C#,我建议你仔细阅读第11章:)

Here's a different way to do it, adding only one line: 这是一种不同的方法,只添加一行:

var query = from p in people
            join pts in pets
            on p equals pts.Owner into grp
            where grp.Any()             // <--- added this
            select new {grp=grp,PersonName=p.FirstName};

Here I select the groups, as you do, but I added one line that selects only the groups that contain at least one element, and ignore the rest. 在这里,我像你一样选择组,但我添加了一行,只选择包含至少一个元素的组,并忽略其余的组。

这也可以在单行代码中使用lambda表达式完成...

IEnumerable<Person> peopleWithPets = people.Where(x => pets.Any(y => y.Owner == x));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM