Как избежать нескольких запросов к одному сложному объекту в ядре EF .net

В .net core 2.2 у меня есть такая модель:

public class A
{
  public ICollection<B> B { get; set; }
}

public class B 
{
  public ICollection<C> C { get; set; }
  public ICollection<D> D { get; set; }
}

public class C
{

}

public class D
{

}

И запрос примерно такой:

var query = from record in Set<A>()
            where record.Id == Id
select new AProjection
{
    BProjection =( from bRecord in Set<B>() 
                    where bRecord.Id = record.BId
    select new BProjection 
    {
        CProjection = bRecord.C.Select( b => new CProjection {/* data here */ }),
        DProjection = bRecord.C.Select( b => new DProjection {/* data here */ })
    })
}

Я хочу вернуть данные в проекцию, но для каждого объекта типа B выполняется запрос для получения объектов типа C и еще один для получения объектов типа D. Как я могу избежать такого поведения?

Это типичная проблема запросов N + 1, рассматриваемая в этом вопросе:

Как избежать запросов n+1 в EF Core 2.1?


person Enrique González    schedule 23.07.2019    source источник


Ответы (1)


EF Core 2.1 представил Оптимизация связанных подзапросов, но, как указано в связанной документации, вам необходимо подключиться для этого, добавив ToList() ко всем проекциям коллекции.

Также по возможности используйте свойства навигации вместо ручных объединений.

e.g.

var query =
    from a in db.Set<A>()
    select new AProjection
    {
        B = (from b in a.B
             select new BProjection
             {
                 C = (from c in b.C select new CProjection { ... }).ToList(), // <--
                 D = (from d in b.D select new DProjection { ... }).ToList(), // <--
             }).ToList() // <--
    };

Всего будет выполнено 4 SQL-запроса — по одному для каждой проекции.

person Ivan Stoev    schedule 24.07.2019