如果有一个自引用表,其中包含一个ParentId属性,该属性保存父记录的ID,我该如何使用ef来加载每个父记录的子记录。
我想要的是将这个cte转换为返回完整层次结构作为集合的方法。
var queryString = @"
;WITH cte AS (
SELECT * FROM [dbo].[Folders] _f WHERE _f.[Id] = @id
UNION ALL
SELECT _c.* FROM [dbo].[Folders] _c
INNER JOIN cte _cte
ON _cte.[Id] = _c.[ParentFolderId]
)
SELECT * FROM cte";
return await this.Entities.FromSql(new RawSqlString(queryString), new SqlParameter("id", id)).ToListAsync();
将子级别的层次结构加载到其父级别中,同时保持一次访问数据库的性能,使其以某种方式转化为可行的形式。
class Folder
{
public int Id { get; set; }
public int? FolderId { get; set; }
public Folder Folder { get; set; }
public IEnumerable<Folder> Children { get; set; }
}
等级结构示例
- Main (Id: 1 / ParentId: null)
- C1 (2/1)
- C11 (4/2)
- C111 (7/4)
- C12 (5/2)
- C2 (3/1)
- C21 (6/3)
- C211 (8/6)
配置关系
builder.Ignore(prop => prop.Folder);
builder.HasOne(prop => prop.Folder).WithMany(prop => prop.Children).HasForeignKey(fk => fk.FolderId);
FromSqlRaw
或FromSqlInterpolated
中使用它,只要DbContext实体正确配置(关系等),EF Core可能能够使用ID重建层次结构。 - undefinedhierarchyid
而不是自引用和EFCore.SqlServer.HierarchyId包。查询肯定会更容易和更快。即使您决定在某个时候移除该包,使用hierarchyid
编写分层SQL查询也会更加轻松。 - undefinedFromSql
方法,如果你使用插值字符串,就要特别小心,否则可能会导致SQL注入问题。这就是为什么在EF Core 3中,针对插值查询和参数化查询有两个单独的方法。 - undefined