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

EF Core 8 + PostgreSQL下递归CTE的EXISTS布尔查询报错:ParentFolderId列不存在(TPT结构)

EF Core 8 + PostgreSQL下递归CTE的EXISTS布尔查询报错:ParentFolderId列不存在(TPT结构)

这个问题的核心原因是你混淆了EF Core实体继承(TPT模式)的逻辑和数据库实际的表结构:

在TPT(Table-Per-Type)映射中,父类DriveItem的属性(比如ParentFolderId、IsDeleted)会被存储在独立的DriveItems父表中,子类Folder仅存储自身独有的属性到Folders子表,两个表通过DriveItemId关联。你当前的SQL错误地从Folders表引用了属于父表的ParentFolderId和IsDeleted字段,所以PostgreSQL提示列不存在——因为Folders表确实没有这两个字段!

修正后的解决方案

我们需要调整SQL,通过关联DriveItems表来获取继承属性,同时保持递归逻辑正确:

public async Task<Result<bool>> HasDeletedAncestorAsync(Guid childFolderId)
{
    const string sql = @"
    WITH RECURSIVE path AS (
        -- 初始层:获取目标文件夹的父ID和删除状态(关联父表DriveItems)
        SELECT 
            f.""DriveItemId"", 
            di.""ParentFolderId"", 
            di.""IsDeleted""
        FROM ""Folders"" f
        JOIN ""DriveItems"" di ON f.""DriveItemId"" = di.""DriveItemId""
        WHERE f.""DriveItemId"" = @p0
        
        UNION ALL
        
        -- 递归层:向上遍历父文件夹,同样关联父表获取属性
        SELECT 
            f.""DriveItemId"", 
            di.""ParentFolderId"", 
            di.""IsDeleted""
        FROM ""Folders"" f
        JOIN ""DriveItems"" di ON f.""DriveItemId"" = di.""DriveItemId""
        JOIN path p ON di.""DriveItemId"" = p.""ParentFolderId""
        WHERE p.""ParentFolderId"" IS NOT NULL
    )
    SELECT EXISTS (
        SELECT 1 FROM path WHERE ""IsDeleted"" = TRUE
    );
    ";

    bool hasDeleted = await DbContext.Database
        .SqlQueryRaw<bool>(sql, childFolderId)
        .SingleAsync();

    return Result.Success(hasDeleted);
}

关键修正点说明

  1. 关联父表获取继承属性:
    所有属于DriveItem父类的属性(ParentFolderId、IsDeleted)必须从DriveItems表查询,而不是Folders子表。我们通过DriveItemId将两个表关联,获取完整的文件夹属性。

  2. 递归逻辑保持正确:
    递归层中,我们通过当前路径的ParentFolderId(即父文件夹的DriveItemId)找到对应的文件夹记录,再关联父表获取其上级ID和删除状态,直到遍历到根目录(ParentFolderId为NULL)。

  3. EF Core 8的SqlQueryRaw用法:
    你的SqlQueryRaw调用本身是正确的(EF Core 8支持直接返回标量类型),问题完全出在SQL的表关联错误上。

为什么你会误解?

在EF Core的实体类中,Folder继承自DriveItem,所以你可以直接通过Folder实体访问ParentFolderId和IsDeleted属性——但这是EF Core提供的抽象,实际数据库中这些属性并不在Folders表中,而是存储在父表DriveItems里。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:03:05