EF Core Automapper 递归查询

EF Core Automapper Recursive Query

我有一个自引用class

public class Project {
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Guid? ParentId { get; set; }    
}

我已经设置了一个 psotgres 数据库,ef core 和 automapper 都可以正常工作。

我的 Dto 如下所示:

public class ProjectDto {
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ICollection<ProjectPathEntry> Path { get; set; } = new HashSet<ProjectPathEntry>();
}

使用 helper-dto

public class ProjectPathEntry {
    public Guid Id { get; set; }
    public string Name { get; set; }
}

问题现在出现在自动映射器配置上:) Id 和 Name 会按照约定自动映射,但路径显然不能直接映射。

我可以用单独的查询填充路径:

var projectPath = await dbContext.Projects.FromSqlInterpolated(
    $@"WITH recursive project(search_id, id, name) AS (
        SELECT p.""Id"", p.""Id"", p.""Name""
        FROM public.""Projects"" p

        UNION ALL

        SELECT p.""Id"", p2.id, p2.name
        FROM public.""Projects"" p, project p2
        WHERE p.""ParentProjectId"" = p2.search_id
    )
    SELECT proj.*
    FROM project
    JOIN public.""Projects"" proj on proj.""Id"" = project.id
    WHERE search_id = {project.Id}
        AND id != {project.Id}"
).ProjectTo<ProjectPathEntry>(mapper.ConfigurationProvider)
.ToListAsync(cancellationToken);

projectPath.Reverse();
project.Path = projectPath;

我能否以某种方式将此查询嵌入到我的自动映射器配置中? 或者是否可以将 SQL-View 添加到我的 pg 数据库并通过 ef 实体配置映射它?

我通过向我的数据库添加一个视图解决了我的问题:

CREATE VIEW "ProjectPathView"("ProjectId", "SortId", "Id", "Name") AS
    WITH RECURSIVE project(search_id, sort_id, id, name) AS (
        SELECT p."Id",
            1,
            p."Id",
            p."Name"
FROM "Projects" p
    UNION ALL
    SELECT p."Id",
        p2.sort_id + 1,
        p2.id,
        p2.name
    FROM "Projects" p,
        project p2
    WHERE p."ParentProjectId" = p2.search_id
)
SELECT project.search_id AS "ProjectId",
    project.sort_id AS "SortId",
    proj."Id",
    proj."Name"    
FROM project
JOIN "Projects" proj ON proj."Id" = project.id;

然后我创建了一个模型

public class ProjectPathEntry
{
    public Guid ProjectId { get; set; }
    public long SortId { get; set; }
    public Guid Id { get; set; }
    public string Name { get; set; }
}

代表我的观点。 在 EF 配置中,我设置了 ToView("ProjectPathView") 设置。 然后我将关系添加到我的基本模型

public class Project {
    ...
        public virtual ICollection<ProjectPathEntry> Path { get; set; } = new HashSet<ProjectPathEntry>();
    ...
}

并设置 HasMany 配置

builder.HasMany(p => p.Path)
       .WithOne()
       .HasForeignKey(p => p.ProjectId);

然后我的ProjectDto上的Path 属性就可以通过Automapper自动映射了