ASP.NET MVC - Entity Framework - Включить с Где [дублировать]

29
задан Beejee 29 May 2013 в 09:46
поделиться

2 ответа

Вы можете запросить требуемые объекты с помощью

Context.Configuration.LazyLoadingEnabled = false;
// Or: Context.Configuration.ProxyCreationEnabled = false;
var buses = Context.Busses.Where(b => b.IsDriving)
            .Select(b => new 
                         { 
                             b,
                             Passengers = b.Passengers
                                           .Where(p => p.Awake)
                         })
            .AsEnumerable()
            .Select(x => x.b)
            .ToList();

. Что здесь происходит, так это то, что вы сначала забираете автобусы и бодрствующие пассажиры из базы данных. Затем AsEnumerable() переключается с LINQ на Entities на LINQ на объекты, что означает, что шины и пассажиры будут материализованы, а затем обработаны в памяти. Это важно, потому что без него EF будет материализовывать окончательный прогноз Select(x => x.b), а не пассажиров.

Теперь EF имеет эту функцию fixup , которая заботится о настройке всех ассоциаций между объектами, которые реализованы в контексте. Это означает, что для каждого Bus теперь загружаются только его бодрые пассажиры.

Когда вы получаете сбор автобусов на ToList, у вас есть автобусы с нужными вами пассажирами, и вы можете сопоставить их с помощью AutoMapper .

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

Существует два способа отключения ленивой загрузки. Отключение LazyLoadingEnabled приведет к повторной активации ленивой загрузки при ее повторном включении. Отключение ProxyCreationEnabled создаст сущности, которые не способны к ленивой загрузке сами , поэтому они не начнут ленивую загрузку после того, как ProxyCreationEnabled снова будет активирован. Это может быть лучшим выбором, когда контекст живет дольше, чем только этот единственный запрос.

Но ... многие-ко-многим

Как уже говорилось, эта работа зависит от отношения исправить. Однако, как объяснено здесь Slauma , исправление отношения не работает со многими ассоциациями. Если Bus - Passenger много-ко-многим, единственное, что вы можете сделать, это исправить:

Context.Configuration.LazyLoadingEnabled = false;
// Or: Context.Configuration.ProxyCreationEnabled = false;
var bTemp = Context.Busses.Where(b => b.IsDriving)
            .Select(b => new 
                         { 
                             b,
                             Passengers = b.Passengers
                                           .Where(p => p.Awake)
                         })
            .ToList();
foreach(x in bTemp)
{
    x.b.Pasengers = x.Passengers;
}
var busses = bTemp.Select(x => x.b).ToList();

... и все это становится еще менее привлекательным.

Сторонние инструменты

Существует библиотека, EntityFramework.DynamicFilters , которая делает это намного проще. Он позволяет определять глобальные фильтры для объектов, которые впоследствии будут применяться в любое время, когда объект запрашивается. В вашем случае это может выглядеть так:

modelBuilder.Filter("Awake", (Person p) => p.Awake, true);

Теперь, если вы это сделаете ...

Context.Busses.Where(b => b.IsDriving)
       .Include(b => b.People)

... вы увидите, что фильтр применяется к включенному коллекция.

Вы также можете включить / отключить фильтры, чтобы вы могли контролировать их, когда они применяются. Я думаю, что это очень аккуратная библиотека.

Существует такая же библиотека от создателя AutoMapper: EntityFramework.Filters

Ядро Entity Framework

Начиная с версии 2.0.0, EF-core имеет фильтры запросов уровня модели . Хотя это отличное дополнение к его функциям, пока ограничение заключается в том, что оно не может быть применено к свойствам навигации, а только к корневой сущности запроса. Надеемся, что в более поздней версии эти фильтры получат более широкое использование.

40
ответ дан Gert Arnold 24 August 2018 в 08:57
поделиться

Отказ от ответственности: Я являюсь владельцем проекта Entity Framework Plus

Функция EF + Query IncludeFilter позволяет фильтровать связанные объекты.

var buses = Context.Busses
                   .Where(b => b.IsDriving)
                   .IncludeFilter(x => x.Passengers.Where(p => p.Awake))
                   .ToList();

Wiki : EF + Query IncludeFilter

17
ответ дан Jonathan Magnan 24 August 2018 в 08:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: