2010-12-21 103 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; } 
    }