EF Core 2.0.1按父分类筛选并获取每组最新2条已审核文章
解决方案:EF Core 2.0.1获取指定父分类下子分类的最新审核文章
你遇到的核心问题是EF Core 2.x版本的Include()方法不支持直接筛选关联实体——它会加载该导航属性的所有关联数据,没法直接给关联集合加过滤条件。不过完全不用切换到ADO.NET,用EF Core就能实现需求,而且优先用Lambda表达式的话,推荐用**投影(Projection)**的方式,刚好符合你只做视图展示的需求。
方法一:投影到匿名类型/DTO(推荐,效率最高)
这种方式让EF Core直接在数据库层面完成筛选、排序和分页,避免不必要的数据加载,代码也简洁:
// 假设你要查询的父分类ID是targetParentCategoryId int targetParentCategoryId = 1; // 替换成你的目标ID var categoryWithArticles = appContext.ArticleCategories // 第一步:筛选出指定父分类下的所有子分类 .Where(c => c.ArticleCategoryParentID == targetParentCategoryId) // 第二步:投影成我们需要的视图模型结构 .Select(category => new { // 分类详情信息 CategoryId = category.Id, CategoryName = category.Name, CategoryDescription = category.Description, // 筛选该分类下已审核的文章,取最新2条 LatestArticles = category.ArticleCategoryRelations .Where(acr => acr.Article.Approved == 1) .Select(acr => acr.Article) .OrderByDescending(a => a.ArticleDate) .Take(2) // 只选择视图需要的文章字段,减少数据传输 .Select(a => new { a.Id, a.Title, a.Slug, a.ArticleDate // 按需添加其他文章字段 }) .ToList() }) .ToList();
为什么不用Include?
EF Core 2.x的Include()设计是加载全部关联数据,没有内置的筛选能力(这个特性在EF Core 3.0+才被加入)。所以如果你硬要用Include,只能先加载所有关联数据再在内存中筛选,这会浪费性能,完全没必要——投影的方式更直接高效。
方法二:手动加载关联数据(不推荐,有N+1问题)
如果你一定要加载完整的实体(虽然你不需要编辑,所以不建议),可以先获取子分类,再逐个查询对应的文章:
int targetParentCategoryId = 1; // 先获取目标子分类 var subCategories = appContext.ArticleCategories .Where(c => c.ArticleCategoryParentID == targetParentCategoryId) .ToList(); // 遍历每个分类,查询符合条件的文章 foreach (var category in subCategories) { category.ArticleCategoryRelations = appContext.ArticleCategoryRelations .Where(acr => acr.ArticleCategoryId == category.Id && acr.Article.Approved == 1) .OrderByDescending(acr => acr.Article.ArticleDate) .Take(2) .Include(acr => acr.Article) .ToList(); }
这个方法的问题是会产生N+1次数据库查询(1次查分类,N次查每个分类的文章),如果子分类数量多,性能会受影响,所以优先选第一种投影方案。
内容的提问来源于stack exchange,提问作者Endri
相关产品推荐
相关产品推荐

