Entity Framework включает Где - PullRequest
       1

Entity Framework включает Где

6 голосов
/ 09 декабря 2011

Если у меня есть запрос, который выглядит следующим образом:

var forms = repo.GetForms().Where(f => f.SubForms.Any(sf => sf.Classes.Any(c => c.TermId == termId)));

Из этого вы можете видеть, что моя схема выглядит следующим образом:

SubForm имеет много Class, который имеет многоTerm.

Что я хочу:

Все SubForms со своими Classes В конкретном Term.

То, что происходит сейчас, так это то, что я получаювсе SubForm, которые имеют какие-либо Class в конкретном Term.Это означает, что SubForm возвращается с ALL child Class, а не только с теми, которые относятся к Term.

Например.У меня есть 2 условия, подчиненная форма с 2 классами в каждом термине.Этот запрос возвращает 4 класса вместо 2 в этом конкретном термине.

Можно ли использовать Include('Expression'), чтобы сказать, что я хочу включить все классы только на основе условия?Или мой запрос неверен?

Ответы [ 5 ]

6 голосов
/ 09 декабря 2011

Используйте это:

var subForms = repo.GetSubForms.Select(sf = new {
        SubForm = sf,
        Classes = sf.Classes.Where(c => c.TermId == termId)
    }).ToList()
    .Select(t => t.SubForm)
    .ToList();

ОБНОВЛЕНИЕ: на основе комментария @ Слаумы:

Если вы хотите загрузить SubForm s, у них есть Class с Term на termId, вы можете переходить от конца к началу;как это:

var subForms = repo.Terms.Where(t => t.Id == termId).Select(t => new {
        Term = t,
        Class = t.Class,
        SubForm = t.Class.SubForm
    }).ToList()
    .Select(t => t.SubForm).ToList();

ИЛИ проще всего, вы можете использовать Include на вашем Term, см .:

var subForms = repo.Terms.Include("Class.SubForm").Where(t => t.Id == termId)
                   .Select(t => t.Class.SubForm).ToList();

ПРИМЕЧАНИЕ: Как я понимаю из вашего вопроса, у вас есть такие отношения:

SubForm has_many Class has_many Term

Но ваш код показывает отношения, подобные этой:

SubForm has_many Class
Term has_many Class

Если можете, поставьте под сомнение ваши сущности или объясните их отношения, пожалуйста.Спасибо.

4 голосов
/ 09 декабря 2011

An Include(Where Expression) не существует.Если вы используете активную загрузку с помощью «Включить», вы всегда будете загружать все элементы.

Существует способ обойти это путем использования проекций.Основная идея заключается в том, что вы выберете новый анонимный тип со свойством, которое вы хотите, и другое свойство с отфильтрованными элементами навигации.EF свяжет их вместе, и в результате вы подделаете Include(Where ... )

Проверьте это для примера .

1 голос
/ 09 декабря 2011

Знаете, иногда я начинаю теряться в причудливых методах расширения LINQ и пытаюсь понять, как с нетерпением загрузить именно то, что мне нужно, и прибегнуть к очень простой концепции "соединения".

var result = 
(from f in SubForums
from c in Classes
from t in Term
where t.TermId = 1
select new { SubForum = f, Class = c, Term = t }).ToList();

Этопростое соединение, которое использует предопределенные свойства навигации (следовательно, вам не нужно указывать условие соединения).Вы возвращаете анонимный тип со всем, что вам нужно.Прелесть этого в том, что Entity Framework сделает для вас автоматическое исправление, поэтому вы можете возвращать SubForum только из вашего метода, если хотите, он будет автоматически содержать класс и последующие ссылки Term.

0 голосов
/ 09 декабря 2011

Это, кажется, распространенный запрос, было трудно найти решение, когда я искал в начале этого года. Я решил использовать решение, включенное в ссылку ниже (я не уверен, что это именно то решение, которое я нашел, но это та же идея) Надеюсь, это поможет!

Фильтрация таблицы «Включает» в запросе Entity Framework

                //Found this method to filter our child objects instead of using .include()
                var Results = (from res in
                                   (from u in DataContext.User
                                    where u.Type.ToUpper() != "ADMIN"
                                    && u.StartDate <= DateTime.Now
                                    && (u.EndDate == null || u.EndDate >= DateTime.Now)
                                    select new
                                    {
                                        User = u,
                                        Access = u.Access.Where(a => a.StartDate <= DateTime.Now
                                                  && (a.EndDate == null || a.EndDate >= DateTime.Now))
                                    }
                                    )
                               select res);

                //The ToArray is neccesary otherwise the Access is not populated in the Users
                ReturnValue = Results.ToArray().Select(x => x.User).ToList();
0 голосов
/ 09 декабря 2011

Я не знаю точных названий отношений, но это должно быть что-то вроде

repo.Terms
    .Include("Classes")
    .Include("Classes.SubForms")
    .SingleOrDefault(x => x.TermId = termId);

// or 

repo.GetSubForms
    .Include("Classes")
    .Where(sf => sf.Classes.Where(c => c.TermId == termId));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...