【问题标题】:Get recursive rootID of parent-child-table with ef-core使用 ef-core 获取父子表的递归 rootID
【发布时间】:2021-02-17 12:35:35
【问题描述】:

我有一个像树列表(父子)一样构建的 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)至少有 1 个子元素。但是元素的深度是未知的。

这里是表格的示例

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

我的任务是查询(使用 EntityFramework Core)给定水果的 RootId。当然,我可以从 db 加载所有实体并在内存中执行,但这并不聪明。 您知道如何编写我的 Linq 以使该任务发生在数据库上吗?

【问题讨论】:

  • 是递归CTE,EF不支持。
  • 你知道是否可以通过 linq-query 调用这个 CTE,是否也可以模拟这个 CTE 进行单元测试。
  • 我发现了如何在我的 linq 查询中调用 CTE。所以现在最后一个问题是,我如何模拟它进行单元测试。
  • 调用 CTE 可以使用“DbFunction”-属性,但我不知道如何为单元测试创​​建模拟(请参阅 stackoverflow.com/questions/53269315/…)。

标签: c# entity-framework linq .net-core entity-framework-core


【解决方案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;
        }
    }
    

【讨论】:

    猜你喜欢
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 2019-05-11
    • 2021-07-29
    • 1970-01-01
    相关资源
    最近更新 更多