LINQ内联接vs左联接
使用扩展语法,我试图在我拥有的两个列表上使用LINQ创建左联接。 以下是来自Microsoft帮助的信息,但我已对其进行了修改,以表明宠物列表中没有任何元素。 我最后得到的是0个元素的列表。 我认为这是因为发生了内部联接。 我要结束的是3个元素(3 Person对象)的列表,其中为缺少的元素填充了空数据。 即左联接。 这可能吗?
Person magnus = new Person { Name = "Hedlund, Magnus" };
Person terry = new Person { Name = "Adams, Terry" };
Person charlotte = new Person { Name = "Weiss, Charlotte" };
//Pet barley = new Pet { Name = "Barley", Owner = terry };
//Pet boots = new Pet { Name = "Boots", Owner = terry };
//Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
//Pet daisy = new Pet { Name = "Daisy", Owner = magnus };
List<Person> people = new List<Person> { magnus, terry, charlotte };
//List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };
List<Pet> pets = new List<Pet>();
// Create a list of Person-Pet pairs where
// each element is an anonymous type that contains a
// Pet's name and the name of the Person that owns the Pet.
var query =
people.Join(pets,
person => person,
pet => pet.Owner,
(person, pet) =>
new { OwnerName = person.Name, Pet = pet.Name }).ToList();
Guy asked 2020-08-12T02:25:12Z
6个解决方案
75 votes
我认为如果您要使用扩展方法,则需要使用GroupJoin
var query =
people.GroupJoin(pets,
person => person,
pet => pet.Owner,
(person, petCollection) =>
new { OwnerName = person.Name,
Pet = PetCollection.Select( p => p.Name )
.DefaultIfEmpty() }
).ToList();
您可能需要使用选择表达式。 如果您有一对多的关系,我不确定它是否会满足您的需求。
我认为使用LINQ Query语法要容易一些
var query = (from person in context.People
join pet in context.Pets on person equals pet.Owner
into tempPets
from pets in tempPets.DefaultIfEmpty()
select new { OwnerName = person.Name, Pet = pets.Name })
.ToList();
17 votes
您需要将连接的对象放入集合中,然后按照JPunyon的说明应用DefaultIfEmpty:
Person magnus = new Person { Name = "Hedlund, Magnus" };
Person terry = new Person { Name = "Adams, Terry" };
Person charlotte = new Person { Name = "Weiss, Charlotte" };
Pet barley = new Pet { Name = "Barley", Owner = terry };
List<Person> people = new List<Person> { magnus, terry, charlotte };
List<Pet> pets = new List<Pet>{barley};
var results =
from person in people
join pet in pets on person.Name equals pet.Owner.Name into ownedPets
from ownedPet in ownedPets.DefaultIfEmpty(new Pet())
orderby person.Name
select new { OwnerName = person.Name, ownedPet.Name };
foreach (var item in results)
{
Console.WriteLine(
String.Format("{0,-25} has {1}", item.OwnerName, item.Name ) );
}
输出:
Adams, Terry has Barley
Hedlund, Magnus has
Weiss, Charlotte has
5 votes
我遇到以下相同问题时出现以下错误信息:
join子句中的表达式之一的类型不正确。 调用“ GroupJoin”时类型推断失败。
当我使用相同的属性名称时,它可以解决。
(...)
join enderecoST in db.PessoaEnderecos on
new
{
CD_PESSOA = nf.CD_PESSOA_ST,
CD_ENDERECO_PESSOA = nf.CD_ENDERECO_PESSOA_ST
} equals
new
{
enderecoST.CD_PESSOA,
enderecoST.CD_ENDERECO_PESSOA
} into eST
(...)
3 votes
这是一篇很好的博客文章,由Fabrice(《 LINQ in Action》的作者)发布,其中涵盖了我提出的问题的材料。 我将其放在此处以供参考,因为该问题的读者会发现这很有用。
将LINQ查询从查询语法转换为方法/运算符语法
2 votes
可以使用DefaultIfEmpty()方法在LINQ中进行左连接。 我没有针对您情况的确切语法...
实际上,我认为如果您只是在查询中将pets更改为pets.DefaultIfEmpty(),它可能会起作用...
编辑:我真的不应该迟到时回答事情...
0 votes
如果您实际上有一个数据库,这是最简单的方法:
var lsPetOwners = ( from person in context.People
from pets in context.Pets
.Where(mypet => mypet.Owner == person.ID)
.DefaultIfEmpty()
select new { OwnerName = person.Name, Pet = pets.Name }
).ToList();