You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 7.0.4如何获取Blazor Server中文件夹的所有父级

解决EF Core获取文件夹所有父级的方案

方法1:用EF Core递归CTE查询(推荐)

EF Core 7原生支持递归CTE(公共表表达式),可以直接从数据库层面一次性拉取所有父级数据,不用反复写Include。

实现代码

先假设你的Folder实体是这样的:

public class Folder
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }
    public Folder Parent { get; set; }
    public ICollection<Folder> Children { get; set; }
}

在FolderService里写递归查询方法:

public async Task<List<Folder>> GetAllAncestors(int folderId)
{
    // 用CTE递归查询所有父级,排除当前文件夹本身
    var ancestors = await _dbContext.Folders
        .FromSqlRaw(@"
            WITH RecursiveAncestors AS (
                SELECT Id, Name, ParentId
                FROM Folders
                WHERE Id = {0}
                UNION ALL
                SELECT f.Id, f.Name, f.ParentId
                FROM Folders f
                INNER JOIN RecursiveAncestors ra ON f.Id = ra.ParentId
            )
            SELECT * FROM RecursiveAncestors
            WHERE Id != {0}", folderId)
        .ToListAsync();

    // 反转后得到从根文件夹到当前文件夹的层级顺序
    ancestors.Reverse();
    return ancestors;
}

这种方式性能最优,因为所有逻辑在数据库端完成,只走一次查询。

方法2:延迟加载+手动递归

如果你的项目已经开启了EF Core延迟加载,可以通过循环遍历Parent属性,逐层加载父级。

实现步骤

  1. 先确保启用延迟加载:
// 在DbContext的OnConfiguring方法里配置
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseLazyLoadingProxies()
                  .UseSqlServer("你的数据库连接字符串");
}
  1. 服务层方法实现:
public async Task<List<Folder>> GetAllAncestors(int folderId)
{
    var ancestors = new List<Folder>();
    var currentFolder = await _dbContext.Folders.FindAsync(folderId);

    // 循环加载父级直到没有父节点
    while (currentFolder?.Parent != null)
    {
        await _dbContext.Entry(currentFolder)
                        .Reference(f => f.Parent)
                        .LoadAsync();
        ancestors.Add(currentFolder.Parent);
        currentFolder = currentFolder.Parent;
    }

    // 反转顺序得到根到当前文件夹的路径
    ancestors.Reverse();
    return ancestors;
}

这种方式适合数据量不大的场景,每次加载一个父级,会产生多次数据库查询。

方法3:内存中递归(小体量场景)

如果你的文件夹总数不多,可以一次性把所有文件夹加载到内存,然后在内存里递归找父级,减少数据库交互次数。

实现代码

public async Task<List<Folder>> GetAllAncestors(int folderId)
{
    var allFolders = await _dbContext.Folders.ToListAsync();
    var ancestors = new List<Folder>();
    var currentId = folderId;

    while (true)
    {
        var currentFolder = allFolders.FirstOrDefault(f => f.Id == currentId);
        if (currentFolder?.ParentId == null) break;

        var parentFolder = allFolders.First(f => f.Id == currentFolder.ParentId.Value);
        ancestors.Add(parentFolder);
        currentId = parentFolder.Id;
    }

    ancestors.Reverse();
    return ancestors;
}

这种方式适合小型系统,文件夹数量少的情况,避免多次查库。

面包屑生成示例

在Blazor组件里调用服务方法后,直接遍历生成面包屑:

@inject FolderService _folderService

@if (breadcrumbs != null && currentFolder != null)
{
    <nav aria-label="breadcrumb">
        <ol class="breadcrumb">
            @foreach (var folder in breadcrumbs)
            {
                <li class="breadcrumb-item">
                    <a href="/folders/@folder.Id">@folder.Name</a>
                </li>
            }
            <li class="breadcrumb-item active" aria-current="page">@currentFolder.Name</li>
        </ol>
    </nav>
}

@code {
    [Parameter] public int FolderId { get; set; }
    private List<Folder> breadcrumbs;
    private Folder currentFolder;

    protected override async Task OnInitializedAsync()
    {
        currentFolder = await _folderService.GetFolderById(FolderId);
        breadcrumbs = await _folderService.GetAllAncestors(FolderId);
    }
}

内容的提问来源于stack exchange,提问作者baseballr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:47:34