Linq to SQL left outer join using Lambda syntax and join on 2 columns (composite join key)
Linq to SQL left outer join using Lambda syntax and joining on 2 columns (composite join key)
我正在尝试使用 Linq to SQL 在 2 列上进行内部连接作为 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
部分。但无论我尝试什么,我都没有得到正确数量的参与者。
我查看了以下现有问题,但 none 在编写正确的 lambda 时解决了我的问题。大多数解决方案都是 lambda 格式的,或者不是多列上的左外连接。
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
您可以通过使用匿名类型来做到这一点。
示例:
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
我能够在 Linq2Sql 和 Entity Framework 中工作的复合外键对 barcode, event_id
上得到这个 LEFT OUTER JOIN
,按照这个 query syntax example 转换为 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
...
备注
这种方法依赖于给相同的匿名 classes 的 automagic equality,即:
Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashCode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.
因此,连接键的两个投影必须是同一类型才能成为 equal
,编译器需要在幕后将它们视为相同的匿名 class,即:
- 两个匿名投影中连接的列数必须相同
- 字段类型必须是相同的兼容类型
- 如果字段名称不同,那么您将需要为它们添加别名(我使用了
JoinColx
)
我已经在 GitHub here 上发布了一个示例应用程序。
遗憾的是, 尚无支持,因此您需要在投影中坚持使用匿名类型。
查询:
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,
};
拉姆达:
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,
});
见code, or clone my git repo,然后玩!
我正在尝试使用 Linq to SQL 在 2 列上进行内部连接作为 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
部分。但无论我尝试什么,我都没有得到正确数量的参与者。
我查看了以下现有问题,但 none 在编写正确的 lambda 时解决了我的问题。大多数解决方案都是 lambda 格式的,或者不是多列上的左外连接。
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
您可以通过使用匿名类型来做到这一点。
示例:
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
我能够在 Linq2Sql 和 Entity Framework 中工作的复合外键对 barcode, event_id
上得到这个 LEFT OUTER JOIN
,按照这个 query syntax example 转换为 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
...
备注
这种方法依赖于给相同的匿名 classes 的 automagic equality,即:
Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashCode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.
因此,连接键的两个投影必须是同一类型才能成为 equal
,编译器需要在幕后将它们视为相同的匿名 class,即:
- 两个匿名投影中连接的列数必须相同
- 字段类型必须是相同的兼容类型
- 如果字段名称不同,那么您将需要为它们添加别名(我使用了
JoinColx
)
我已经在 GitHub here 上发布了一个示例应用程序。
遗憾的是,
查询:
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,
};
拉姆达:
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,
});
见code, or clone my git repo,然后玩!