LINQ左连接和右连接

raj*_*aja 25 c# linq-to-sql

我需要帮助,

我有两个名为A和B的dataTable,我需要来自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
Run Code Online (Sandbox Code Playgroud)

我需要外出:

User | age| Data |Growth
------------------------                           
1    |2   |43.5  |46.5                           
2    |3   |44.5  |                          
3    |4   |45.6  |
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 41

您提供的示例数据和输出未演示左连接.如果是左连接,您的输出将如下所示(请注意我们如何为用户1提供3个结果,即用户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  |
Run Code Online (Sandbox Code Playgroud)

假设您仍然需要左连接; 以下是您在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
              };
Run Code Online (Sandbox Code Playgroud)

如果您想进行正确的连接,只需交换您选择的表格,如下所示:

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
              };
Run Code Online (Sandbox Code Playgroud)

代码的重要部分是into语句,后跟DefaultIfEmpty.这告诉Linq如果另一个表中没有匹配的结果,我们希望有默认值(即null).


Vit*_*nov 5

琼斯医生展示了左外连接,但正确的答案会略有不同 - 因为在原始问题中,应该使用两个与年龄字段相关联的表,以便根据代码获得完全符合要求的结果.

....
//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; }
    }
Run Code Online (Sandbox Code Playgroud)