使用连接阻止实体框架查询中的SELECT N + 1问题

时间:2017-06-02 08:11:42

标签: c# entity-framework

我试图将间接相关实体中的某些内容查询到单一用途的视图模型中。这是我的实体的责备:

public class Team {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Member> Members { get; set; }
}

public class Member {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Pet {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public Member Member { get; set; }
}

每个类都在我的数据库上下文中的DbSet<T>

这是我想从查询构建的视图模型:

public class PetViewModel {
    public string Name { get; set; }
    public string TeamItIndirectlyBelongsTo { get; set; }
}

我使用此查询执行此操作:

public PetViewModel[] QueryPetViewModel_1(string pattern) {
    using (var context = new MyDbContext(connectionString)) {
        return context.Pets
            .Where(p => p.Name.Contains(pattern))
            .ToArray()
            .Select(p => new PetViewModel {
                Name = p.Name,
                TeamItIndirectlyBelongsTo = "TODO",
            })
            .ToArray();
    }
}

但显然还有一个&#34; TODO&#34;在那里。

Gotcha:我目前无法更改实体,因此我无法在{{1}上添加List<Pet>属性或Team属性帮帮忙。我想暂时解决查询中的问题。

这是我目前的解决方案:

Member

然而,这有一个&#34; SELECT N + 1&#34;问题在那里。

有没有办法只创建一个 EF查询来获得所需的结果,而无需更改实体?

PS。如果你喜欢&#34;即插即用&#34;包含上述内容的repro,请参阅this gist

1 个答案:

答案 0 :(得分:3)

由于没有提供必要的导航属性,你已经做了很多事情,因为@Evk在评论中提到的不会影响你的数据库结构,但是当你写{{1}时,允许EF提供必要的连接(这里你需要的)。

您的模型的另一个问题是,由于“加入”,您既没有从pet.Member.Team.NameTeam,也没有从PetPet的导航路径实体Team没有导航属性。

通过使用现有的导航属性和不常见的Member运算符,仍然可以通过单个查询获得所需的信息,而不是那么直观:

join