C# 使用EF Core 5.0加载自引用实体(只需在其导航属性中获取父对象及其子对象)

C# 使用EF Core 5.0加载自引用实体(只需在其导航属性中获取父对象及其子对象),c#,entity-framework-core,ef-core-3.1,self-reference,ef-core-5.0,C#,Entity Framework Core,Ef Core 3.1,Self Reference,Ef Core 5.0,我想实现一个评论系统这是我的评论实体 public class Comment { public int CommentId { get; set; } public int? ParentId { get; set; } public string Content { get; set; } public DateTimeOffset DateCreated { get; set; } public D

我想实现一个评论系统这是我的评论实体

 public class Comment
    {
        public int CommentId { get; set; }
        public int? ParentId  { get; set; }
        public string Content { get; set; }
        public DateTimeOffset DateCreated { get; set; }
        public DateTimeOffset DateModified { get; set; }


        public Comment Parent { get; set; }
        public ICollection<Comment> Children { get; set; }


    }
公共类注释
{
public int CommentId{get;set;}
public int?ParentId{get;set;}
公共字符串内容{get;set;}
public DateTimeOffset DateCreated{get;set;}
public DateTimeOffset DateModified{get;set;}
公共注释父项{get;set;}
公共ICollection子项{get;set;}
}
这是我在Fluent API中的配置


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Comment>(comment =>
            {
                comment.HasKey(c => c.CommentId);
                comment.HasIndex(c => c.ParentId);

                comment.HasOne(c => c.Parent)
                       .WithMany(c => c.Children)
                       .HasForeignKey(c => c.ParentId);
            });
        }

模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
实体(注释=>
{
HasKey(c=>c.CommentId);
comment.HasIndex(c=>c.ParentId);
comment.HasOne(c=>c.Parent)
.有许多(c=>c.儿童)
.HasForeignKey(c=>c.ParentId);
});
}
一切正常,我可以用这段代码加载所有具有层次结构的记录(包括父记录和子记录)

  List<Comment> comments = await _db.Comments.Include(c => c.Children)
                .ToListAsync();
List comments=await\u db.comments.Include(c=>c.Children)
.ToListAsync();
但此代码加载所有元素,例如子元素。但我想让所有的父母,然后是他们的孩子,然后是孙子和

我将此代码用于此场景

List<Comment> comments = await _db.Comments.Include(c => c.Children)
                .Where(c => c.ParentId == null)
                .ToListAsync();
List comments=await\u db.comments.Include(c=>c.Children)
.Where(c=>c.ParentId==null)
.ToListAsync();
这段代码只是把所有的父母和他们的孩子一起加载,而不是大孩子和其他层次结构中的孩子


如何编写此查询?

我找到了此场景的解决方案

  public async Task<IActionResult> Index()
        {

            List<Comment> comments = await _db.Comments.AsNoTrackingWithIdentityResolution()
                                                        .Include(c => c.Children)
                                                        .ToListAsync();

            // Structure Comments into a tree
            List<Comment> commentsTree = comments.Where(c => c.ParentId == null)
                                                 .AsParallel()
                                                 .ToList();

            return View(commentsTree);
        }

公共异步任务索引()
{
列表注释=等待_db.comments.AsNoTrackingWithIdentityResolution()
.包括(c=>c.儿童)
.ToListAsync();
//将注释结构化到树中
列表commentsTree=comments.Where(c=>c.ParentId==null)
.天冬酰胺()
.ToList();
返回视图(commentsTree);
}

这是一个非常复杂的查询,我建议将其写入服务器上的存储过程或表值函数中,然后从EF查询。EF没有游标的概念,我相信你会发现你需要它们。或者至少是非常精确的CTE查询。请查找有关LINQ+层次结构或递归的其他问题。这是一个不断重复的话题。