我试图检索基于其子实体的属性的实体列表-并包括那些相同的子实体。我正在使用EntityFramework Core 3.1,虽然我很高兴升级到5。X,如果有任何改变可以帮我解决这个问题。到目前为止,除了一些非常基本的CRUD样板,我还没有探索过EntityFramework,所以我不确定这是更面向linq的还是特定于EF (Core)的东西。下面是一个非常简化的项目方法示例,我将使用它最终将数据返回给我的API的消费者。
兴趣点(POI
)有许多历史记录(History
)。POI有一个List<History>
,一个History有一个PointID
,它被EF Core用来填充POI的List<History>
。
下面是我如何获得所有poi及其历史记录的方法,其中一个点自某个日期以来首次注册(使用此方法的可空日期参数)
var result = _context.POIs
.Where(point => (registeredSince == null || point.RegisteredAt >= registeredSince))
.Include(point => point.Histories)
.ToList();
然而,我的问题是……然后,我如何根据该POI
的History
中的属性仅获得POI
s(并包括相同的History
记录?)或者,举个例子;我想只返回具有areaId == 5
的History
记录的POI
s(并将其包括在结果中)
如果没有非常深入的EF知识,一种方法是:
- 首先运行查询返回
History
实体,其中history.areaId == 5
只选择history.PointId
- 第二个查询将获得所有
POI
,其中id
在上面返回的PointId
列表中 - . .
history.areaId == 5
(副本) 包括
History
然而,我将其中的一部分运行两次,这似乎效率低下。基本上,我可以有效地使用LINQ/EF来获得所有POI
s,其中history.areaId == 5
(然后仅包括areaId
为5的History
记录)?在我能够缩小结果之前,我是否必须写一些不可避免地加载所有POI
及其History
记录的东西,或者是EF可以愉快地做的事情?
您可以使用EF Core 5中引入的Filtered include。X,查询类似-
var result = _context.POIs
.Include(p => p.Histories.Where(h => h.areaId == 5))
.ToList();
这将返回POI
的列表,其中每个列表将只包含areaId == 5
.
编辑:
如果您只想要具有History
和areaId == 5
的POI
s,您可以简单地相应地过滤它们-
var result = dbCtx.POIs
.Include(p => p.Histories.Where(h => h.areaId == 5))
.Where(p => p.Histories.Any(h => h.areaId == 5))
.ToList();
您应该能够使用以下命令:
var result = _context.POIs
.Include(poi => poi.Histories)
// Enumerate linked Histories & get the areaId from each into a list)
// ... then see if that list contains the areaID we're looking for.
.Where(poi => poi.Histories.Select(h => h.areaId).Contains(areaIdParam))
.ToList();