2016-04-18 3 views
2

Моя цель - сделать только одну поездку в базу данных и получить Заказы с фильтрованной дочерней коллекцией.Entity Framework 6.1.3: Проекция - загрузка детей детей напрямую

Для достижения этой цели я использовал проекции:

using (var db = new context()) 
      { 
       var query = from o in db.Orders 
          select 
           new 
           { 
            Order = o, 
            Events = o.Events.Where(
             e => e.SomeBool 
             && e.SomeBool2 
            ), 

            EventsGroups = o.Events.Where(
             e => e.SomeBool 
             && e.SomeBool2 
            ).Select(e => e.Groups), 

           }; 
      } 

Проблема здесь в том, что сбор ребенка, «Группы» о событиях, не загружен. Чтобы решить эту проблему, я загрузил ее как другое свойство «EventsGroups» в запросе, которое затем я смогу вместе с событиями впоследствии.

Мой вопрос: Есть ли способ загрузить ребенка «Группы» в «Событие» напрямую, так что мне не нужно их использовать в качестве другого имущества?

Вдоль линий

Events = o.Events.Where(
e => e.SomeBool 
&& e.SomeBool2 
).Include(e => e.Groups), //this cannot be done this way 

Почему я, используя проекцию, а не жадной загрузки:

https://msdn.microsoft.com/en-us/magazine/hh205756.aspx

Filtering include items in LINQ and Entity Framework

Базовые классы:

public class Order 
{ 
    public Order() 
    { 
     Events = new HashSet<Event>(); 
    } 

    public int Id { get; set; } 

    public virtual ICollection<Event> Events { get; set; } 
} 

public class Event 
{ 
    public Event() 
    { 
     Groups = new HashSet<Group>(); 
    } 

    public int Id { get; set; } 

    public bool SomeBool { get; set; } 

    public bool SomeBool2 { get; set; } 

    public virtual ICollection<Group> Groups { get; set; } 
} 

public class Group 
{ 
    public Group() 
    { 
     Events = new HashSet<Event>(); 
    } 

    public int Id { get; set; } 

    public string Name { get; set; } 

    public virtual ICollection<Event> Events { get; set; } 
} 
+0

вы можете попробовать 'o.Events.include (е => e.Groups) .где (...'? – SWilko

+0

Вы имеете в виду внутри проекции? Я не верю, что Include существует там http://imgur.com/ZOOXx0E – Archigo

+0

извините, что вы правы. Я думаю, что ответ @Ivans ниже должен работать. – SWilko

ответ

0

Поскольку Include не может быть объединено с анонимным проекции, необходимо спроектировать Event.Groups так же, как вы проецируете Order.Events, то есть, используя другой анонимный тип проекции:

var query = from o in db.Orders 
      select new 
      { 
       Order = o, 
       Events = (from e in o.Events 
          where e.SomeBool && e.SomeBool2 
          select new 
          { 
           Event = e, 
           Groups = e.Groups, 
          }), 
      }; 
+0

Это намного более красиво, чем мой способ сделать это, и проще собрать. Я подозреваю, что это близко, поскольку я могу избежать избегания циклов для создания объектов DTO из любых объектов. – Archigo

+0

Если у вас есть объекты DTO, вы можете напрямую проектировать их вместо анонимных типов - EF поддерживает это. –

0

вы можете загрузить все, установив Configuration.LazyLoadingEnabled = true;, без необходимости какой-либо Include, конечно ... perfoamnce должны установить в виду .. зависит ..

public MyDatabaseContext(string databaseName) 
     : base(databaseName) 
    { 
     Configuration.LazyLoadingEnabled = true; 
    } 
+0

Это ломается с моей целью только одной поездки в базу данных. – Archigo

0

Я считаю, что это должно работать для вас:

using (var db = new context()) 
{ 
    var query = db.Orders 
    .Include(o=>o.Events) 
    .Include(o=>o.Events.Select(e=>e.Groups)) 
    .Select(o=>new 
    { 
     Order = o, 
     Events = o.Events.Where(e => e.SomeBool && e.SomeBool2) 
    }); 
} 

, если нет, то это будет:

using (var db = new context()) 
{ 
    var query = db.Orders 
    .Include(o=>o.Events) 
    .Include(o=>o.Events.Select(e=>e.Groups)) 
    .Select(o=>new Order 
    { 
     Id=o.Id, 
     Events = o.Events.Where(e => e.SomeBool && e.SomeBool2).ToList() 
    }); 
} 
+0

Это не сработало во время тестирования. Группы не загрузились. Получение заказов и отфильтрованных событий выполняется, но для групп есть только пустой список. Вложения, похоже, ничего не делают, поскольку это тот же результат с ними или без них. – Archigo

+0

Хм. Интересно. Простое исправление заключается в добавлении '.ToList()' между Include и Select. Это определенно будет работать, однако вы будете получать все записи событий, а не только те, которые соответствуют вашим условиям «.Where». –

Смежные вопросы