C# 使用ef core获取父子表的递归rootID

C# 使用ef core获取父子表的递归rootID,c#,entity-framework,linq,.net-core,entity-framework-core,C#,Entity Framework,Linq,.net Core,Entity Framework Core,我有一个SQL表,它的构建类似于树列表(父-子)。意味着你有rootId和childId。每个实体都有一个ParentId。如果ParentId为null,则该元素是根项 这里是分层体系结构的一个示例 - Fruit (1) - TreeFruits (2) - Apple (4) - Bulb (5) - SeaFruits (3) - DeepSeaFruits (6) - Sushi (9) - Kraken (13) - S

我有一个SQL表,它的构建类似于树列表(父-子)。意味着你有rootId和childId。每个实体都有一个ParentId。如果ParentId为null,则该元素是根项

这里是分层体系结构的一个示例

- Fruit (1)
  - TreeFruits (2)
    - Apple (4)
    - Bulb (5)
  - SeaFruits (3)
    - DeepSeaFruits (6)
      - Sushi (9)
      - Kraken (13)
    - Shrimp (7)
    - Fish (8)
- Vegetable (10)
  - Carrot (11)
  - Potato (12)
您可以看到每个根元素(数字1和10)至少有一个子元素。但元素的深度还不清楚

下面是一个表格的示例

------------
| Id*      |<---
|          |   |
| ParentId |----
| Name     |
------------
------------

|Id*|如果您不想从数据库加载所有记录,然后对其进行处理,则有两种选择:

解决方案1:在数据库中编写存储过程和处理

解决方案2:编写一个递归函数,向数据库发送多个请求(以根深度为单位)

下面是解决方案2的一个函数:

    public async Task<int> GetRoot(int id)
    {
        var current = await _dbContext.Set<Entity>().Where(p => p.Id == id).FirstOrDefaultAsync();
        if (current.ParentId is not null)
        {
            return await GetRoot(current.ParentId.Value);
        }
        else
        {
            return current.Id;
        }

    }
    
公共异步任务GetRoot(int-id)
{
var current=await_dbContext.Set(),其中(p=>p.Id==Id.FirstOrDefaultAsync();
if(current.ParentId不为null)
{
return wait GetRoot(current.ParentId.Value);
}
其他的
{
返回当前.Id;
}
}

这是递归CTE,EF不支持。您知道是否可以通过linq查询调用此CTE,以及是否可以模拟此CTE进行单元测试。我在linq查询中找到了如何调用CTE的方法。现在最后一个问题是,如何为单元测试模拟它。调用CTE可以使用“DbFunction”-属性,但我不知道如何为单元测试创建模拟(请参阅)。