NotSerializableException при сохранении ArrayList в текстовый файл

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

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 имеет фильтры запросов уровня модели . Хотя это отличное дополнение к его функциям, пока ограничение заключается в том, что оно не может быть применено к свойствам навигации, а только к корневой сущности запроса. Надеемся, что в более поздней версии эти фильтры получат более широкое использование.

0
задан wattostudios 16 April 2012 в 18:14
поделиться