2010-12-21 190 views
20

我需要幫助,LINQ左連接和右加入

我有兩個dataTable的稱爲A和B,我需要從A的所有行和B的匹配行

例:

A:           B: 

User | age| Data       ID | age|Growth         
1 |2 |43.5        1 |2 |46.5 
2 |3 |44.5        1 |5 |49.5 
3 |4 |45.6        1 |6 |48.5 

我需要出認沽:

User | age| Data |Growth 
------------------------       
1 |2 |43.5 |46.5       
2 |3 |44.5 |       
3 |4 |45.6 | 

回答

26

您提供的不表現出左側示例數據和輸出連接。如果這是一個左連接你的輸出應該是這樣的(注意我們如何有3個結果,用戶1,即每進行一次成長記錄用戶1擁有):

User | age| Data |Growth 
------------------------       
1 |2 |43.5 |46.5       
1 |2 |43.5 |49.5  
1 |2 |43.5 |48.5  
2 |3 |44.5 |       
3 |4 |45.6 | 

假設你仍然需要一個左連接;這裏是你如何做一個左連接Linq中:

var results = from data in userData 
       join growth in userGrowth 
       on data.User equals growth.User into joined 
       from j in joined.DefaultIfEmpty() 
       select new 
       { 
        UserData = data, 
        UserGrowth = j 
       }; 

如果你想要做一個正確的加入,只是交換你是從在選擇表,就像這樣:

var results = from growth in userGrowth 
       join data in userData 
       on growth.User equals data.User into joined 
       from j in joined.DefaultIfEmpty() 
       select new 
       { 
        UserData = j, 
        UserGrowth = growth 
       }; 

重要部分代碼是進入聲明,然後是DefaultIfEmpty。這告訴Linq,如果在另一個表中沒有匹配的結果,我們希望有默認值(即null)。

4

瓊斯醫生顯示左外連接,但正確的答案會略有不同 - 因爲在原始問題中,兩個錶鏈接在年齡字段上,以便根據需要使用以下代碼來精確地得到結果。

.... 
//ctx = dataContext class - not shown here. 
var user1 = new UserData() { User = 1, Age = 2, Data = 43.5 }; 
var user2 = new UserData() { User = 2, Age = 3, Data = 44.5 }; 
var user3 = new UserData() { User = 3, Age = 4, Data = 45.6 }; 

ctx.UserData.AddRange(new List<UserData> { user1, user2, user3 }); 

var growth1 = new UserGrowth() { Id = 1, Age = 2, Growth = 46.5 }; 
var growth2 = new UserGrowth() { Id = 1, Age = 5, Growth = 49.5 }; 
var growth3 = new UserGrowth() { Id = 1, Age = 6, Growth = 48.5 }; 

ctx.UserGrowth.AddRange(new List<UserGrowth> { growth1, growth2, growth3 }); 

var query = from userData in ctx.UserData 
         join userGrowth in ctx.UserGrowth on userData.Age equals userGrowth.Age 
          into joinGroup 
         from gr in joinGroup.DefaultIfEmpty() 
         select new 
         { 
          User = userData.User, 
          age = userData.Age, 
          Data = (double?)userData.Data, 
          Growth = (double?)gr.Growth 
         }; 

Console.WriteLine("{0} | {1} | {2} | {3}", "User", "age", "Data", "Growth"); 
      foreach (var x in query) 
      { 
       Console.WriteLine("{0} | {1} | {2} | {3}", x.User, x.age, x.Data, x.Growth); 
      } 


.... with following entity classes: 

public class UserData 
    { 
     [Key] 
     public int User { get; set; } 
     public int Age { get; set; } 
     public double Data { get; set; } 
    } 

    public class UserGrowth 
    { 
     public int Id { get; set; } 
     public int Age { get; set; } 
     public double Growth { get; set; } 
    }