首页 > 解决方案 > EF Core - 带有嵌套评论的讨论板

问题描述

我正在尝试制作一个类似于 Reddit 的讨论板,其中一个帖子可以有多个评论,每个评论可以有多个评论,每个评论可以有多个评论,等等。

我将如何编写查询以返回包含其所有评论的特定帖子,以及所有评论的评论以及所有这些评论的评论等?我考虑过使用 .ThenInclude() 但这是不可能的,因为我不知道提前有多少嵌套评论。

这是我目前拥有的,但它只检索对帖子的直接回复,没有任何嵌套评论:

selected = await context.Posts
                    .Include(p => p.Author)
                    .Include(p => p.SavedBy)
                    .Include(p => p.HiddenBy)
                    .Include(p => p.UpvotedBy)
                    .Include(p => p.DownvotedBy)
                    .Include(p => p.Replies.Where(c => !c.HiddenBy.Contains(user)))
                        .ThenInclude(c => c.Author)
                    .Include(p => p.Replies)
                        .ThenInclude(c => c.SavedBy)
                    .Include(p => p.Replies)
                        .ThenInclude(c => c.HiddenBy)
                    .Include(p => p.Replies)
                        .ThenInclude(c => c.UpvotedBy)
                    .Include(p => p.Replies)
                        .ThenInclude(c => c.DownvotedBy)
                    .SingleAsync(p => p.Id == id);

模型:

public abstract class Entry
    {
        public Entry()
        {
            Replies = new List<Comment>();
            SavedBy = new List<ApplicationUser>();
            HiddenBy = new List<ApplicationUser>();
            UpvotedBy = new List<ApplicationUser>();
            DownvotedBy = new List<ApplicationUser>();
        }

        public int Id { get; set; }
        public string Content { get; set; }
        public DateTime DateCreated { get; set; }
        public int Upvotes { get; set; }
        public int Downvotes { get; set; }
        public int VoteScore { get; set; }

        public ApplicationUser Author { get; set; }
        public ICollection<Comment> Replies { get; set; }
        public ICollection<ApplicationUser> SavedBy { get; set; }
        public ICollection<ApplicationUser> HiddenBy { get; set; }
        public ICollection<ApplicationUser> UpvotedBy { get; set; }
        public ICollection<ApplicationUser> DownvotedBy { get; set; }
    }

    public class Post : Entry
    {
        public string Title { get; set; }
    }

    public class Comment : Entry
    {
        public Entry RepliedTo { get; set; }
        public Post Post { get; set; }
    }

数据库上下文:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
        }

        public DbSet<Entry> Entries { get; set; }
        public DbSet<Post> Posts { get; set; }
        public DbSet<Comment> Comments { get; set; }
    }

标签: c#asp.net-mvcentity-framework.net-coreentity-framework-core

解决方案


想一想查询在 SQL 而不是 C#/LINQ 中的外观。由于关系将是递归的,因此您需要为需要预取的许多层显式定义连接。这会让您丢失任何层之外的数据。或者,您可以使用由存储过程绑定的游标。不。相反,评论可以有一个指向其父评论的指针,但也可以有一个指向 MOST 父实体(原始帖子)的外键。然后,当您获得帖子的所有评论时,您可以将所有评论作为平面数组检索,然后在 c#(SQL 之外)中构建树。这应该性能更高。


推荐阅读