【问题标题】:LINQ Lambda Left join with an Inner joinLINQ Lambda 左连接和内连接
【发布时间】:2015-05-29 09:22:22
【问题描述】:

我已经编写了一个 LINQ lambda 查询,到目前为止它返回了所有没有相关培训行的员工,这些员工工作正常。我现在需要修改 where 子句以使用经理 id 将经理表加入员工。

我有点不确定如何修改这个左连接 lambda 以包含一个内连接。如果有人能指出我正确的方向,那将不胜感激。

    var managerId = 1;

    var query = db.staff

                .GroupJoin(db.training,
                    s => s.id,

                    t => t.staff_id,
                    (s, t) => new {Staff = s, Training = t.FirstOrDefault()})

    //TODO: join manager.id on staff.manager_id


            .Where(st => st.Training==null);//TODO: modify where clause && manager.id == managerId 

谢谢

【问题讨论】:

  • 感谢您的回复,我正在考虑沿着查询表达式路线走,但想看看是否有人可以帮助我学习 Lambda 表达式,而不是任何事情
  • 您可以简单地添加staff.Where(s => s.managerId == managerId)。但我认为你应该使用导航属性,而不是连接。如果您需要帮助,请出示班级模型。

标签: c# linq lambda


【解决方案1】:

内连接使用 Join 方法执行。我认为您的查询应该是这样的:

var query = db.staff
              .GroupJoin(db.training,
                         s => s.id,
                         t => t.staff_id,
                         (s, t) => new { Staff = s, Training = t.FirstOrDefault() })
              .Join(db.manager,
                    gj => gj.Staff.manager_id,
                    m => m.id,
                    (gj, m) => new { Staff = gj.Staff, Training = gj.Training, Manager = m })
              .Where(st => st.Training == null
                        && st.Manager.id == managerId);

【讨论】:

  • 不确定,但在 where 子句之后执行内部联接可能更有效,这样它就不会打扰加入左联接过滤掉的记录。您可以有多个 where 子句(因此,GroupJoin(training)、Where(Training == null)、Join(manager)、Where(Manager.Id == managerId)。我想这取决于您使用的 LINQ 提供程序...
  • 这个 lambda 表达式正在返回我期待的结果——完美!根据您的评论,我将看看查询的效率。非常感谢! :)
  • 如果将gj => gj.Staff.manager_id 改为使用Training,您将如何做到这一点?像这样gj => gj.Training.???
  • 是的,gj 变量的类型在GroupJoin 的第4 个参数中定义,它是一个匿名类型,成员为Staff 和Training。如果 id 没有匹配的 staff_id 值,则培训可能有它的默认值,如果它是引用类型,则应该为 null。假设您可以使用 C#6 空条件运算符将管理器集合内部连接到 Training.staff_id - 将 Join 调用的第二个参数更改为:gj => gj.Training?.staff_id
【解决方案2】:

您可以执行以下操作(我没有使用方法链接语法来使其更具IMO 可读性):

var query = from s in db.staff
            join m in db.manager on s.manager_id equals m.id
            join t in db.training on s.id equals t.staff_id into tr
            from training in tr.DefaultIfEmpty()
            select new
            {
                Staff = s,
                Training = training
            };

【讨论】:

    【解决方案3】:

    可能是这样的:

    var query = from s in db.staff
        join m in db.manager on s.manager_id equals m.id
        from t in db.training
            .Where(w=>w.staff_id==s.id).DefaultIfEmpty()
        select new
        {
            Staff = s,
            Training = training
        };
    

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多