Как использовать предложение where в свойстве суб-навигации с помощью linq и ef

Моя модель имеет свойство навигации, а это свойство навигации имеет другое свойство суб-навигации. Мне нужно использовать where clause в свойстве суб-навигации для фильтрации результатов.

Я пытаюсь использовать запрос linq, но не могу получить результаты

_context.Set<Job>().Include(x=>x.Premises).ThenInclude(y=>y.Station.Where(s=>s.)

Следующее соединение sql дает мне желаемые результаты

select * 
  from [dbo].[JOB] J inner join 
       [dbo].[PREMISES] P on J.PremisesId = P.Id inner join 
       [dbo].[STATION] S on P.StationCode=S.StationCode
 where S.StationCode = '001'

Любые идеи?

Пожалуйста, покажите свойства навигации. Есть ли какие-нибудь из них коллекции?

Yacoub Massad 11.04.2018 11:48
1
1
78
1

Ответы 1

Обратите внимание на эти похожие операторы LINQ:

var jobs = db.Jobs
                .Include(j => j.Premises)
                .Include(j => j.Premises.Select(p => p.Stations))
                .ToList();

var stations = db.Stations
                .Include(s => s.Premise)
                .Include(s => s.Premise.Job)
                .ToList();

Хотя ваш возвращаемый тип отличается, вы, по сути, храните одни и те же данные в памяти. Я мог бы использовать второе, чтобы получить все рабочие места:

var jobs_from_stations = stations.Select(s => s.Premise.Job).Distinct();

И jobs_from_stations, и jobs будут содержать одни и те же данные.

Однако есть разница в фильтрации.

Если бы вы добавили в этот запрос предложение Where(), он работал бы иначе.

Первый запрос будет фильтровать в рамках сущности Job, тогда как второй будет фильтровать в рамках сущности Station. Поскольку в настоящее время вы пытаетесь выполнить фильтрацию на основе свойства станции, предлагается использовать второй запрос:

var stations = db.Stations
                .Include(s => s.Premise)
                .Include(s => s.Premise.Job)
                .Where(s => s.StationCode == "001")
                .ToList();

Если вы хотите, чтобы возвращаемый тип был списком заданий:

var jobs = db.Stations
                .Include(s => s.Premise)
                .Include(s => s.Premise.Job)
                .Where(s => s.StationCode == "001")
                .Select(s => s.Premise.Job)
                .Distinct()
                .ToList();

Обратите внимание, что вместо этого можно было бы использовать первый запрос, но он становится более подробным и громоздким:

var jobs = db.Jobs
                .Include(j => j.Premises)
                .Include(j => j.Premises.Select(p => p.Stations))
                .Where(j => j.Premises.Any(p => p.Stations.Any(s => s.StationCode == "001")))
                .ToList();

Как правило, я всегда стараюсь использовать начать с ребенка и продвигаться вверх. Как вы видите в приведенном выше примере, это упрощает фильтрацию. Но, возможно, вы также заметили, что он также сохраняет простые инструкции Include():

.Include(s => s.Premise)
.Include(s => s.Premise.Job)

вместо

.Include(j => j.Premises)
.Include(j => j.Premises.Select(p => p.Stations))

Хотя эти два примера функционально эквивалентны, необходимость добавления Select() для каждого уровня становится очень громоздкой, если вы хотите включить объекты, которые являются несколькими отношениями, удаленными с того места, где вы начали.

Другие вопросы по теме