Как использовать предложение where для свойства суб-навигации, используя linq и EF

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

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

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

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

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'

Есть идеи?

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

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