Linq to SQL使用Lambda语法并在2列上进行了左外部联接(复合联接键)

VDW*_*WWD 5 c# sql-server asp.net lambda linq-to-sql

我正在尝试使用Linq to SQL作为Lambda表达式在2列上进行内部联接。普通查询如下所示。

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

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

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

问题在于,使用上述Lambda时,我得到了太多结果,因为它缺少AND participants.event_id = prereg_participants.event_id零件。但是,无论我怎么努力,我都没有得到正确数量的参与者。

我查看了以下现有问题,但是在编写正确的lambda时没有一个解决了我的问题。而且大多数解决方案都是lambda格式的nog或不是多列上的Left外部联接。

如何在LINQ中在单个联接中的多个字段上进行联接

LINQ to SQL-具有多个联接条件的左外部联接

通过Lambda表达式使用两个以上的列进行分组

而其中大部分来自此Google搜索

Ada*_*Cox 6

询问:

        var petOwners =
            from person in People
            join pet in Pets
            on new
            {
                person.Id,
                person.Age,
            }
            equals new
            {
                pet.Id,
                Age = pet.Age * 2, // owner is twice age of pet
            }
            into pets
            from pet in pets.DefaultIfEmpty()
            select new PetOwner
            {
                Person = person,
                Pet = pet,
            };
Run Code Online (Sandbox Code Playgroud)

拉姆达:

        var petOwners = People.GroupJoin(
            Pets,
            person => new { person.Id, person.Age },
            pet => new { pet.Id, Age = pet.Age * 2 },
            (person, pet) => new
            {
                Person = person,
                Pets = pet,
            }).SelectMany(
            pet => pet.Pets.DefaultIfEmpty(),
            (people, pet) => new
            {
                people.Person,
                Pet = pet,
            });
Run Code Online (Sandbox Code Playgroud)

查看代码,或者克隆我的 git repo,然后开始玩!


Stu*_*tLC 4

我能够在 Linq2Sql 和实体框架中工作的LEFT OUTER JOIN复合外键对上得到这个barcode, event_id,按照此查询语法示例转换为 lambda 语法。

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

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

笔记

这种方法依赖于赋予相同匿名类的自动相等性,即:

由于匿名类型的 Equals 和 GetHashCode 方法是根据属性的 Equals 和 GetHashCode 方法定义的,因此仅当同一匿名类型的所有属性都相等时,两个实例才相等。

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

  • 两个匿名投影中连接的列数必须相同
  • 字段类型必须是相同类型兼容的
  • 如果字段名称不同,那么您需要为它们添加别名(我已经使用过JoinColx

我已在GitHub上发布了一个示例应用程序。

遗憾的是,表达式树中尚不支持值元组,因此您需要在投影中坚持使用匿名类型。