使用EntityFramework.Core从自引用表加载完整层次结构

解释为什么这个问题不同于: EF – 多个包括急切加载分层数据。 不好的做法?

  1. 可能的重复是基于意见的问题,如果这是一个不好的做法,而我的问题往往得到如何做的技术解决方案,独立于意见,如果这是一个好的做法。 我将此决定留给产品所有者,需求工程师,项目经理和想要该function的客户。
  2. 给出的答案要么解释为什么这是一个不好的做法,要么使用一种对我不起作用的方法(使用Include()和ThenInclude()产生硬编码深度,而我需要灵活的深度)。

在当前项目(.NET核心web api)中,我尝试从自引用表中加载层次结构。

经过谷歌搜索后,我很惊讶这样的任务(我认为这是微不足道的)似乎并不是微不足道的。

好吧,我有这个表来形成我的层次结构:

CREATE TABLE [dbo].[Hierarchy] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Parent_Id] INT NULL, [Name] NVARCHAR (50) NOT NULL, PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_Hierarchy_Hierarchy] FOREIGN KEY ([Parent_Id]) REFERENCES [dbo].[Hierarchy] ([Id]) ); 

在web api中,我尝试返回完整的层次结构。 一个可能特别的事情(可能会有所帮助)就是我要加载完整的表格。

我也知道我可以使用预先加载和导航属性(子项的Parent和InverseParent)

 _dbContext.Hierarchy.Include(h => h.InverseParent).ThenInclude(h => h.InverseParent)... 

问题是这会加载硬编码深度(例如,如果我使用1 Include()和5 ThenInclude(),则为六个级别),但我的层次结构具有灵活的深度。

任何人都可以通过给我一些代码来帮助我,如何加载整个表(例如,在1 DB调用的最佳方案中进入内存),然后让方法返回完整的层次结构?

事实上,由于所谓的EF(核心) 关系修复,加载整个层次结构非常容易。

假设我们有以下型号:

 public class Hierarchy { public int Id { get; set; } public string Name { get; set; } public Hierarchy Parent { get; set; } public ICollection Children { get; set; } } 

然后是以下代码

 var hierarchy = db.Hierarchy.Include(e => e.Children).ToList(); 

将使用正确填充的ParentChildren属性加载整个层次结构。

当您需要加载层次结构的一部分时,引用的post中描述的问题就出现了,由于LINQ中缺少类似CTE的支持,这很难实现。

我已经构建了存储过程来使用递归cte 存储过程获取所有级别的所有子级,以使用Entity Framework和递归cte获取任何级别的自引用表的所有子ID