Linq的SelectMany方法使用示例

在EF中,由于数据库表之间存在外键,类似下面的实体随处可见(对象有一个集合类型属性):

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Nullable<int> Age { get; set; }

    public virtual ICollection<Pet> Pets { get; set; }
}

若要求页面按如下格式展示数据,试考虑如何写Linq语句:

引用内容 引用内容
person1,pet1
person2,pet2
person3,pet3

简单的inner join可以用Join方法实现:

var data = context.People.Join(context.Pets, person => person.Id, pet => pet.Pid, (person, pet) => new { Name = person.Name, PName = pet.Name });

针对这种特殊结构的对象,还可以用SelectMany来实现:

var data = context.People.SelectMany(person => person.Pets, (person, pet) => new { Name = person.Name, PName = pet.Name });

这好像看不出优势,但若要实现left join,那就非用SelectMany不可了:

var data = context.People.GroupJoin(context.Pets, person => person.Id, pet => pet.Pid, (person, pets) => new { person = person, pets = pets }).SelectMany(item => item.pets.DefaultIfEmpty(), (item, pet) => new { Name = item.person.Name, PName = pet == null ? "-" : pet.Name });
//or
var data = context.People.SelectMany(person => person.Pets.DefaultIfEmpty(), (person, pet) => new { Name = person.Name, PName = pet == null ? "-" : pet.Name });

SQL Server Profiler捕获对应sql语句:

Select
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
CASE WHEN ([Extent2].[Id] IS NULL) THEN N'-' ELSE [Extent2].[Name] END AS [C1]
FROM  [dbo].[Person] AS [Extent1]
LEFT OUTER JOIN [dbo].[Pet] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Pid]


评论: 0 | 引用: 0 | 查看次数: 3656
发表评论
登录后再发表评论!