2009-12-09 15 views
10

Ich möchte nur die Personen auswählen, die Haustiere haben.C# Linq Inner Join

wenn ich die Abfrage

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 ausführen nicht Haustier auch ausgewählt hat bekommen.

Meine Listen sind

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

Antwort

19

Das ist, weil Sie join ... into verwenden, die eine Gruppe beitritt. Sie wollen einfach nur ein normales beitreten:

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

Alternativ, wenn Sie die Menschen mit Haustieren und ihre Besitzer mögen, können Sie so etwas wie tun könnten:

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

, dass ein Ergebnis geben wird, wo man bekommen kann Jeder Besitzer und seine Haustiere, aber nur für Leute, die Haustiere haben.

Wenn Sie etwas anderes wollen, lassen Sie es uns wissen ...

By the way, wäre jetzt ein guter Zeitpunkt, um über das Objekt und Auflistungsinitialisierer zu lernen. Hier ist ein einfacher Weg, um Ihre people Liste zu initialisieren, zum Beispiel:

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

viel kompakter :)

EDIT: Ein Cross-Join ist einfach:

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

Left Joins effektiv emuliert mit Gruppe verbindet. Wie es klingt wie Sie C# in Tiefe haben, empfehle ich Ihnen, Kapitel 11 gelesen gründlich :)

+1

‚in grp‘ verschwunden sein sollte, nicht wahr? ; p – leppie

+0

@leppie: Doh! Fixed, thanks :) –

+0

Wir haben es behoben :) Das 'in' ändert den lexikalischen Bereich, der mich immer außerhalb der IDE verwirrt. – leppie

5

Hier ist eine andere Art und Weise, es zu tun, das Hinzufügen nur eine Zeile:

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

Hier wähle ich die Gruppen Wie Sie, aber ich habe eine Zeile hinzugefügt, die nur die Gruppen auswählt, die mindestens ein Element enthalten, und den Rest ignorieren.

+0

Ahh das ist was meine Meinung war auf der Suche nach :) – leppie

+0

OOps! Es gibt das Ergebnis. – Udana

4

dies auch getan werden kann, Lambda-Ausdrücke in einer einzigen Codezeile mit ...

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