【发布时间】:2019-10-19 14:29:25
【问题描述】:
我有一个项目的这个模型:
public class Project
{
public int Id { get; set; }
public int? ParentId { get; set; }
public Member ProjectOwner { get; set; }
public List<Project> ChildProjects { get; set; }
// ... more properties
}
我想为所有项目加载所有子项目及其ProjectOwner。在我的设置中,在我们到达“叶子”之前,后代尾巴的长度没有设定限制。
目前,我正在为Index-view 执行此操作(是的,这很糟糕!):
List<Project> projects = await db.Projects
.Where(p => p.ParentId == null)
.Include(o => o.ProjectOwner)
.Include(c => c.ChildProjects)
.ThenInclude(o => o.ProjectOwner)
.Include(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(o => o.ProjectOwner)
.Include(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ProjectOwner)
.Include(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ProjectOwner)
.Include(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ChildProjects)
.ThenInclude(c => c.ProjectOwner)
// ... and so on ... (!)
.ToListAsync();
如何以更有效和动态的方式加载所有内容?上述代码仅限于固定数量的级别。我不能拥有那个。
几天前我问了similar question,但无法从回复中得出任何结论。
【问题讨论】:
-
对于 所有 项目,这很容易 - 请参阅 stackoverflow.com/questions/46160780/…。基本上
var rootProjects = db.Projects.Include(p => p.ProjectOwner).Include(p => p.ChildProjects).AsEnumerable().Where(p => p.ParentId == null).ToList(); -
显式加载绝对可以解决您使用 n 包含的问题。但是,这是有代价的。如果这棵树中有 20 个叶子,您将获得 20 个 SQL 查询。不推荐用于大型应用程序。您可以尝试使用
Fixing Up来解决该问题,其中缓存了数据库上下文对象检索到的数据,并用于填充为后续查询创建的对象的导航属性。但修复起来很棘手,需要通过检查发送到数据库的 SQL 查询来进行反复试验。 -
我回答了类似的问题here
-
@IvanStoev 太棒了!这似乎适用于项目列表。但是只有一个怎么样?
-
不幸的是,由于 LINQ/EF Core 中缺乏递归查询支持,因此没有简单/良好/高效的过滤集解决方案。
标签: c# recursion asp.net-core-mvc entity-framework-core