我的模型有一个导航属性,此导航属性具有另一个子导航属性。我需要在子导航属性上使用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'
有什么想法吗?
答案 0 :(得分: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()
变得非常麻烦。