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