【问题标题】:Left join multiple tables using lambda expression使用 lambda 表达式左连接多个表
【发布时间】:2016-11-17 13:12:40
【问题描述】:

我有 2 张桌子:

specs {specId, desc, createdby, lastupdatedby}
用户 {userid, 用户名}

我希望下面的 linq 查询需要用纯 lambda 表达式编写

    from spec in specs
    from user in users.where(x => x.userId== spec.createdby).DefaultIfEmpty()
    from updatedUser in users.where(x => x.userId== spec.lastupdatedbyby).DefaultIfEmpty()
select new {
spec = spec
user = user,
updatedUser = updatedUser
}

请帮忙。

数据就像说:

spec[{1, test, 1234, 2345},{2, test1, 1234, null}]

users[{1234, Allen},{2345, Dwayne}]

所以结果应该是

[{1, test, Allen, Dwayne}, {2, test1, Allen, null}]

【问题讨论】:

  • 你能分享列表和你想要的结果吗?
  • @Eldeniz 我刚刚用示例数据和结果更新了我的问题。
  • @RustinCohle 请检查我的答案
  • @RustinCohle 不,它不支持左连接。我更新了答案:我花了一些时间解决这个问题,因为我从未遇到过这个问题。这是一个非常有趣的练习。请查看更新后的答案。
  • @RustinCohle 当然可以,请参阅我的更新答案。我列举了结果变量,但如果您愿意,您可以在 Linq 查询末尾的 ToList 方法调用之后将 ForEach 方法调用加入队列

标签: c# linq lambda


【解决方案1】:

让我们从这些类开始:

class Specs {
    public int specId { get; set; }
    public string desc { get; set; }
    public int createdby { get; set; }
    public int lastupdatedby { get; set; }
}

class Users {
    public int userId { get; set; }
    public string username { get; set; }
}

class UpdatedUser {
    public int userId {get; set;}
    public string username { get; set; }
}

现在是 Linq 查询,为方便起见,我创建了一些示例数据:

var specs = new Specs[]
{
    new Specs{specId = 1, desc = "Spec1", createdby=1, lastupdatedby=1},
    new Specs{specId = 2, desc = "Spec2", createdby=2, lastupdatedby=3},    
    new Specs{specId = 3, desc = "Spec3", createdby=3, lastupdatedby=1},
    new Specs{specId = 4, desc = "Spec4", createdby=3, lastupdatedby=3},
};

var user = new Users[]
{
    new Users{userId = 1, username = "User1"},
    new Users{userId = 2, username = "User2"},
};

var updatedUser = new UpdatedUser[]
{
    new UpdatedUser{userId = 1, username = "UpdatedUser1"},
    new UpdatedUser{userId = 2, username = "UpdatedUser2"},         
};

var result = specs
    .GroupJoin(user, 
        s => s.createdby,
        u => u.userId,
    (s, u) => u.Select(x => new {spec = s, user = x})
            .DefaultIfEmpty(new {spec = s, user = (Users)null}))
.SelectMany(g => g)
.GroupJoin(updatedUser,
        firstJoin => firstJoin.spec.lastupdatedby,
        uu => uu.userId,
        (firstJoin, uu) => 
        uu.Select(y => new {spec = firstJoin.spec, user = firstJoin.user, updatedUser = y})
.DefaultIfEmpty(new {spec = firstJoin.spec, user = firstJoin.user, updatedUser = (UpdatedUser) null}))
    .SelectMany(g1 => g1)
    .ToList();

GroupJoin 扩展方法可帮助您获得一个元组,其中包含起始表的所有元素以及连接表的元素列表。

现在如果你列举结果:

result.ForEach(item => {
    Console.WriteLine(item.spec.desc);
    Console.WriteLine(item.user != null ? item.user.username : "NULL");
    Console.WriteLine(item.updatedUser != null ? item.updatedUser.username : "NULL");
    Console.WriteLine();
});

你得到这个:

Spec1
User1
UpdatedUser1

Spec2
User2
NULL

Spec3
NULL
UpdatedUser1

Spec4
NULL
NULL

【讨论】:

    【解决方案2】:

    你可以试试

    var list = specs.Join(users,
                    s => s.lastupdatedby,
                    u => u.userid,
                    (s, u) => new { specs = s, users = u })
                    .Select(x => new {
                        specId = x.specs.specId,
                        desc = x.specs.desc,
                        createdby=x.specs.createdby,
                        username=x.users.username
    
                    }).ToString();
    

    【讨论】:

      【解决方案3】:
      LEFT JOIN MULTIPLE TABLES
      ------------------------
      
      create table Rama(rid int,name varchar(80),zip int);
      create table Kris(kid int,rid int, Title varchar(80),zip int);
      
      insert into Rama values(1,'Robert Rama' ,10001),
                             (2,'Roger Raju'  ,10002),
                             (3,'Kevin Kali'  ,10003),
                             (4,'Mark Mutu'   ,10004)
      
      insert into Kris values(0,0,'NP' ,10001),
                             (1,1,'VP' ,10001),
                             (2,2,'AVP',10002)
      
      //Lambda expression
      //Download https://www.linqpad.net/Download.aspx
      //Create tables as given below and connect linqpad to your db
      //select C#  statement(s) on linqpad and  run below
      var v =
      from r in Ramas
      join k in Kris
        on new { r.Rid, r.Zip } equals new { k.Rid, k.Zip }
        into resultGroups
      from k in resultGroups.DefaultIfEmpty()
      select new { r.Rid, r.Name, k.Title };
      
      v.Dump();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-14
        • 1970-01-01
        • 2021-09-16
        • 1970-01-01
        • 1970-01-01
        • 2014-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多