С# Linq Inner Join

Я хочу выбрать только тех, у кого есть домашние животные.

когда я выполняю запрос

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[] 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);
 }

Ответ 1

Это потому, что вы используете join ... into, который объединяет группу. Вы просто хотите нормальное соединение:

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

В качестве альтернативы, если вы хотите, чтобы люди с домашними животными и их владельцы, вы могли бы сделать что-то вроде:

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

Это даст результат, когда вы можете получить каждого владельца и своих питомцев, но только для людей, у которых есть домашние животные.

Если вы хотите что-то еще, сообщите нам...

Кстати, сейчас самое подходящее время для изучения инициализаторов объектов и коллекций. Здесь более простой способ инициализировать ваш список 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" },
};

Гораздо более компактно:)

РЕДАКТИРОВАТЬ: крест-соединение легко:

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

Левые соединения эффективно эмулируются с помощью групповых объединений. Похоже, у вас есть С# в Depth, я предлагаю вам внимательно прочитать главу 11:)

Ответ 2

Здесь другой способ сделать это, добавив только одну строку:

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};

Здесь я выбираю группы, как и вы, но я добавил одну строку, которая выбирает только группы, содержащие хотя бы один элемент, и игнорирует остальные.

Ответ 3

это также можно сделать, используя лямбда-выражения в одной строке кода...

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