问题描述
有一个自引用表,它的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();
通过某种方式将孩子的层次结构加载到他们的父母中,同时保持一次db访问的性能。
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);
解决方法
如果您希望在一个查询中使用整个层次结构,那很容易。只需检索所有文件夹,如果启用了更改跟踪,EF将修复所有关系。 IE(如果您刚刚运行)
var folders = db.Set<Folder>().ToList();
您将拥有填充所有导航属性的整个层次。
,就这样。
cte
var rawSqlQuery= @"
;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";
然后使用LINQ进行过滤。
(await this.Entities.FromSql(
new RawSqlString(rawSqlQuery),new SqlParameter("@id",id))
.ToListAsync())
.SingleOrDefault(f => f.Id == id);