2009-02-08 225 views
41

使用擴展語法我試圖在兩個使用LINQ的列表上創建一個左連接。以下是來自Microsoft的幫助,但我已將其修改爲顯示寵物列表中沒有元素。我最終得到的是0個元素的列表。我認爲這是因爲內部連接正在發生。我想結束的是3個元素(3個Person對象)的列表,其中填充缺失元素的空數據。即左連接。這可能嗎?LINQ Inner-Join vs Left-Join

Person magnus = new Person { Name = "Hedlund, Magnus" }; 
Person terry = new Person { Name = "Adams, Terry" }; 
Person charlotte = new Person { Name = "Weiss, Charlotte" }; 

//Pet barley = new Pet { Name = "Barley", Owner = terry }; 
//Pet boots = new Pet { Name = "Boots", Owner = terry }; 
//Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte }; 
//Pet daisy = new Pet { Name = "Daisy", Owner = magnus }; 

List<Person> people = new List<Person> { magnus, terry, charlotte }; 
//List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy }; 
List<Pet> pets = new List<Pet>(); 

// Create a list of Person-Pet pairs where 
// each element is an anonymous type that contains a 
// Pet's name and the name of the Person that owns the Pet. 
var query = 
    people.Join(pets, 
       person => person, 
       pet => pet.Owner, 
       (person, pet) => 
        new { OwnerName = person.Name, Pet = pet.Name }).ToList(); 

回答

71

,如果你想使用擴展方法我認爲你需要使用GroupJoin

var query = 
    people.GroupJoin(pets, 
        person => person, 
        pet => pet.Owner, 
        (person, petCollection) => 
         new { OwnerName = person.Name, 
           Pet = PetCollection.Select(p => p.Name) 
               .DefaultIfEmpty() } 
        ).ToList(); 

您可能不得不玩的選擇表達。我不確定在你有一對多關係的情況下它會給你想要的。

我認爲這是與LINQ查詢語法更容易一些

var query = (from person in context.People 
      join pet in context.Pets on person equals pet.Owner 
      into tempPets 
      from pets in tempPets.DefaultIfEmpty() 
      select new { OwnerName = person.Name, Pet = pets.Name }) 
      .ToList(); 
+1

wohoo :)沒錯我在找什麼! – Ekaterina 2009-10-30 10:18:31

+0

我不知道你可以通過在查詢方法周圍放置括號來獲得.ToList(),謝謝! – Haroon 2012-02-01 12:22:08

+2

請不要調用LINQ聲明性查詢語法「LINQ語法」。它們都是「LINQ語法」。正確的命名是「查詢語法」與「方法語法」。 http://msdn.microsoft.com/en-us/library/bb397947。aspx – Pluc 2014-12-18 18:34:31

2

使用DefaultIfEmpty()方法可以在LINQ中左連接。我沒有你的情況下,雖然確切的語法...

其實我覺得,如果你只需要改變寵物pets.DefaultIfEmpty()在它可能工作查詢...

編輯:我真的當其後期不應該回答的東西......

15

你需要獲得參加對象爲一組,然後應用DefaultIfEmpty爲JPunyon說:

Person magnus = new Person { Name = "Hedlund, Magnus" }; 
Person terry = new Person { Name = "Adams, Terry" }; 
Person charlotte = new Person { Name = "Weiss, Charlotte" }; 

Pet barley = new Pet { Name = "Barley", Owner = terry }; 
List<Person> people = new List<Person> { magnus, terry, charlotte }; 
List<Pet> pets = new List<Pet>{barley}; 

var results = 
    from person in people 
    join pet in pets on person.Name equals pet.Owner.Name into ownedPets 
    from ownedPet in ownedPets.DefaultIfEmpty(new Pet()) 
    orderby person.Name 
    select new { OwnerName = person.Name, ownedPet.Name }; 


foreach (var item in results) 
{ 
    Console.WriteLine(
     String.Format("{0,-25} has {1}", item.OwnerName, item.Name)); 
} 

輸出:

Adams, Terry    has Barley 
Hedlund, Magnus   has 
Weiss, Charlotte   has 
5

我當面臨同樣的問題以下錯誤消息:

聯接子句中的類型的表達式中的一個的不正確。在「GroupJoin」調用中,類型推斷失敗。

解決當我使用相同的屬性名稱,它的工作。

(...)

join enderecoST in db.PessoaEnderecos on 
    new 
     { 
     CD_PESSOA   = nf.CD_PESSOA_ST, 
     CD_ENDERECO_PESSOA = nf.CD_ENDERECO_PESSOA_ST 
     } equals 
    new 
    { 
     enderecoST.CD_PESSOA, 
     enderecoST.CD_ENDERECO_PESSOA 
    } into eST 

(...)

0

如果你確實有一個數據庫,這是最簡單的方法:

var lsPetOwners = (from person in context.People 
        from pets in context.Pets 
         .Where(mypet => mypet.Owner == person.ID) 
         .DefaultIfEmpty() 
        select new { OwnerName = person.Name, Pet = pets.Name } 
        ).ToList();