EntityFramework 5 фильтрует включенное свойство навигации
Я хотел бы найти способ использования Linq для фильтрации свойства навигации для подмножества связанных объектов. Я знаю, что все ответы по этому вопросу предлагают сделать анонимный селектор, например:
query.Where(x => x.Users.Any(y => y.ID == actingUser.ID))
.Select(x => new
{
Event = x,
Discussions = x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())
})
.OrderBy(x => x.Discussions.Count())
.ThenBy(x => x.Event.Name);
Однако это значительно меньше идеального из-за общей природы генерации запросов, а также дает значительно ужасные SQL-запросы, если вы выкидываете профилировщик.
Я хотел бы иметь возможность выполнить что-то вроде:
query.Include(x => x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>()))
.OrderBy(x => x.Discussions.Count())
.ThenBy(x => x.Name);
Я понимаю, что это не поддерживается в EF5 (или любой версии, если на то пошло), но должен быть способ добиться ограничения набора результатов через Linq, не вникая в утверждения анонимного типа.
Я попытался сделать что-то под мелодию:
query.GroupJoin(discquqery,
x => x.ID,
x => x.Event.ID,
(evt, disc) => evt.Discussions = disc.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())).ToList();
Однако вы не можете иметь назначение внутри выражения лямбда и выбор анонимного типа здесь вызывает ту же дилемму, что и при использовании select.
Я думаю, я не могу понять, почему EF не предоставляет способ (который я могу найти) для генерации:
SELECT
--Properties
FROM Event e
LEFT OUTER JOIN Discussions d
ON e.ID = d.EventID AND --Additional constraints
WHERE
--Where conditions
ORDER BY
--Order Conditions
Так просто ограничить соединение в SQL там, чтобы быть способом сделать это через Linq, а также.
PS: Я искал стек, MSDN, обмен экспертами и т.д. Пожалуйста, поймите, что это не дубликат. Все, что касается даже этой темы, либо имеет ответ "Это не может быть сделано", либо ответ вообще. Нет ничего невозможного... включая это.
Ответы
Ответ 1
Все, что касается касания этого предмета, либо имеет отклик "Не может быть" ответ" или вообще не отвечать. Ничто не невозможно... включая это.
Конечно. Возможно. Вы можете скачать исходный код EF и добавить эту функцию самостоятельно. Это будет большой вклад в проект с открытым исходным кодом и сообщество. Я считаю, что команда EF с радостью поможет вам в ваших усилиях.
В текущей версии "это не может быть сделано" - это ответ. Вы можете использовать проекцию для анонимного или специального неотображаемого типа, как описано в начале вашего вопроса. Другие параметры - это отдельный явный запрос для загрузки связанных объектов для одного родителя или отдельного запроса для загрузки связанных объектов для всех родителей.
Загрузка отношений для одного родителя:
context.Entry(event)
.Collection(e => e.Discussions)
.Query()
.Where(d => ...)
.Load();
Загружать отношения для всех родителей (требуется отключение ленивой загрузки):
// load all parents
var events = query.Where(e => ...).ToList();
// load child filtered by same condition for parents and new condition for children
childQuery.Where(d => e.Event ... && d.Something ...).Load();
Второе решение требует, чтобы ребенок имел свойство навигации обратно к родительскому (для построения того же условия запроса, которое первоначально использовалось для загрузки родителя). Если у вас все правильно настроено и привязаны сущности, EF должен автоматически фиксировать ваши отношения (коллекции) в родительских сущностях (но он не будет отмечать коллекцию в динамическом прокси, как загруженный, поэтому вы не можете использовать это вместе с ленивой загрузкой).