代码之家  ›  专栏  ›  技术社区  ›  VDWWD

使用lambda语法的Linq to SQL左外部联接和2列上的联接(复合联接键)

  •  4
  • VDWWD  · 技术社区  · 6 年前

    我正在尝试对两列进行内部联接,其中Linq to SQL作为lambda表达式。普通查询如下所示。

    SELECT * FROM participants 
    LEFT OUTER JOIN prereg_participants ON prereg_participants.barcode = participants.barcode
    AND participants.event_id = prereg_participants.event_id
    WHERE (participants.event_id = 123)
    

    我成功地用以下代码在一列上进行了左外部联接。

    var dnrs = context.participants.GroupJoin(
        context.prereg_participants,
        x => x.barcode,
        y => y.barcode,
        (x, y) => new { deelnr = x, vi = y })
        .SelectMany(
        x => x.vi.DefaultIfEmpty(),
        (x, y) => new { deelnr = x, vi = y })
        .Where(x => x.deelnr.deelnr.event_id == 123)
        .ToList();
    

    问题是,对于上面的lambda,我得到的结果太多,因为它缺少 AND participants.event_id = prereg_participants.event_id 部分。但是无论我怎么尝试,我都得不到正确的参与者数量。

    我研究了以下现有的问题,但没有一个解决了我写正确lambda的问题。大多数解决方案都是lambda格式的nog,或者不是多个列上的左外部联接。

    How to do joins in LINQ on multiple fields in single join

    LINQ to SQL - Left Outer Join with multiple join conditions

    Group By using more than two columns by Lambda expression

    这些大部分来自 this Google search

    2 回复  |  直到 6 年前
        1
  •  1
  •   StuartLC    6 年前

    我能拿到这个 LEFT OUTER JOIN 关于复合外键对 barcode, event_id 在linq2sql和实体框架中工作,并根据此转换为lambda语法 query syntax example .

    这通过创建一个匿名投影来实现,该投影用于匹配连接条件的左侧和右侧:

    var dnrs = context.participants.GroupJoin(
        context.prereg_participants,
        x => new { JoinCol1 = x.barcode, JoinCol2 = x.event_id }, // Left table join key
        y => new { JoinCol1 = y.barcode, JoinCol2 = y.event_id }, // Right table join key
        ...
    

    笔记

    这种方法依赖于 automagic equality 给相同的匿名类,即:

    因为匿名类型上的equals和gethashcode方法是根据属性的equals和gethashcode方法定义的,所以只有当相同匿名类型的两个实例的所有属性都相等时,它们才相等。

    因此,对于连接键的两个投影,需要具有相同的类型才能 equal 编译器需要在后台将它们视为相同的匿名类,即:

    • 两个匿名投影中联接列的数目必须相同
    • 字段类型必须是同一类型,并且兼容
    • 如果字段名不同,则需要对它们进行别名(我已使用 JoinColx )

    我在上安装了一个示例应用程序 GitHub here .

    可悲的是,还没有人支持 value tuples in expression trees ,所以您需要在投影中坚持匿名类型。

        2
  •  -1
  •   kashi_rock    6 年前

    您可以通过使用匿名类型来实现这一点。

    例子:

    var result = from a in context.participants
                 join b context.prereg_participants on new { X = a.barcode, Y = a.event_id } equals new { X = b.barcode, Y = b.event_id } into A
                 from b in A.DefaultIfEmpty()
                 where a.event_id = 123