LINQ查询,n + 1个问题

时间:2019-04-25 06:30:49

标签: c# .net-core ef-core-2.2

我有一个包含三个子查询的查询,但我的问题是子查询针对每个国家(n + 1)运行。

由于主要查询大约有70行,因此我简化了查询以使其更易于阅读,并更改了域以使其更易于理解。

我已经尝试过将城市/山脉/河流包括在内,并在子查询中运行.ToList(),但无济于事。

// The CountryDto class I'm selecting to.
public class CountryDto
{
    public string CountryName { get; set; }
    public IEnumerable<CityDto> CityDtos { get; set; }
    public IEnumerable<MountainDto> MountainDtos { get; set; }
    public IEnumerable<RiverDto> RiverDtos { get; set; }
}
// The query
var query = _db.Countries
    .Select(country => new CountryDto
    {
        CountryName = country.Name,
        CityDtos = country.Citites
            .Where(city => city.Population > 10000)
            .Select(city => new CityDto
            {
                Name = city.Name,
            }),
        MountainDtos = country.Mountains
            .Where(mountain => mountain.Height > 100)
            .Select(mountain => new MountainDto
            {
                Name = mountain.Name,
            }),
        RiverDtos = country.Rivers
            .Where(river => river.Length > 1000)
            .Select(river => new RiverDto
            {
                Name = river.Name,
            }),
    })
    .Where(c => c.CityDtos.Any() || c.MountainDtos.Any() || c.RiverDtos.Any());

var totalCount = query.Count();
var countries = await query.ToListAsync();

2 个答案:

答案 0 :(得分:0)

Entity Framework Core支持在客户端上评估部分查询并将其部分推送到数据库。由数据库提供者决定将在数据库中评估查询的哪些部分。

就您而言,我猜所有.Any部分都在客户端进行评估。您可以配置代码以引发异常以进行客户端评估。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
        .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}

有关更多信息,https://docs.microsoft.com/en-us/ef/core/querying/client-eval

答案 1 :(得分:0)

最终将查询分为 const routes: Routes = [ { path: '', component: LayoutComponent, canActivate: [AuthGuard], children: [ { path: 'home', loadChildren: './home/home.module#HomeModule', data: { title: 'Home' } }, { path: '', redirectTo: 'home', pathMatch: 'full' } ] }, { path: 'unauthorized', component: UnauthorizedComponent, canActivate: [ReverseAuthGuard], data: { title: 'Unauthorized' } }, { path: 'login', component: LoginComponent, canActivate: [ReverseAuthGuard], data: { title: 'Login' } } ]; 部分作为计数和.Where()部分作为结果,这消除了我的n + 1问题。

.Select()