请教各位大佬,ToTree树型查询如何限制子列表的返回记录数呢? 返回

SqlSugar 沟通中
12 409
该叫什么 yookt 发布于2024/2/6
悬赏:0 飞吻


如题,我想实现一个读取文章评论的功能,其中Repiles是该条评论的回复信息列表(代码如下)。

为了减轻服务器负担,每条评论我想只读取该评论的前5条回复内容,我尝试在ToTree后面加Take方法,但是不起作用。.ToTree(...).Take(5);

请问大佬们,这个功能如何实现呢?

    [SugarTable("comments")]
    public class CommentInfor
    {
        /// <summary>
        /// 评论编号
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public long ID { get; set; }
        /// <summary>
        /// 评论人编号
        /// </summary>
        public int UID { get; set; }        
        /// <summary>
        /// 所属的评论编号(回复)
        /// </summary>
        public long ParentID { get; set; }
        /// <summary>
        /// 文章编号
        /// </summary>
        public long ArticleID { get; set; }
        /// <summary>
        /// 评论内容
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 评论回复列表
        /// </summary>
        [SugarColumn(IsIgnore = true)]
        public List<CommentInfor> Replies { get; set; }
    }
    
    ///获取文章的评论列表
    public static ListResult<CommentInfor> GetComments(int articleID)
    {
        var data = db.Queryable<CommentInfor>()
        .Where(i => i.ArticleID == articleID).Take(10)
        .ToTree(i => i.Replies, i => i.ParentID, 0); //此处返回了全部符合条件的记录,如何限制只返回前5条记录呢?
        return new ListResult<CommentInfor>(data);
    }


热忱回答12

  • 级别不多 可以用导航查询


    includes(it=>Child.Take(5).ToList(),it=>it.Child.Take(5).ToList(),it=>it.Child.Take(5).ToList())

    .ToList();

    0 回复
  • yookt yookt VIP0
    2024/2/6

    @fate sta:谢谢大佬的回复,我之前是用的一对多导航查询,但导航查询有一个功能我一直实现不了。

    CommentInfor中其实还有个字段Commenter(评论人的名称) 用了导航查询,是要读取另一张用户表里的字段值。用了导航查询好像就没有办法在子列表中再进行一对一导航了,完整代码如下:

        [SugarTable("comments")]
        public class CommentInfor
        {
            /// <summary>
            /// 评论编号
            /// </summary>
            [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
            public long ID { get; set; }
            /// <summary>
            /// 评论人编号
            /// </summary>
            public int UID { get; set; }        
            /// <summary>
            /// 所属的评论编号(回复)
            /// </summary>
            public long ParentID { get; set; }
            /// <summary>
            /// 文章编号
            /// </summary>
            public long ArticleID { get; set; }
            /// <summary>
            /// 评论内容
            /// </summary>
            public string Content { get; set; }        
            /// <summary>
            /// 回复的目标用户编号
            /// </summary>
            public int ReplyToUID { get; set; }
            /// <summary>
            /// 回复的目标用户昵称
            /// </summary>
            [Navigate(NavigateType.OneToOne, nameof(ReplyToUID))]
            public string ReplyToUser { get; set; }
            /// <summary>
            /// 评论人昵称
            /// </summary>
            [Navigate(NavigateType.OneToOne, nameof(UID))]
            public string Commenter { get; set; }
            /// <summary>
            /// 评论回复列表
            /// </summary>
            [SugarColumn(IsIgnore = true)]
            public List<CommentInfor> Replies { get; set; }
        }
         
        ///获取文章的评论列表
        public static ListResult<CommentInfor> GetComments(int articleID)
        {
          if (!db.ConfigQuery.Any())//保证只配置一次不能更新,该配置是全局静态存储
          {
             db.ConfigQuery.SetTable<UserInfor>(it => it.UID, it => it.Nickname);
          }
          var data = db.Queryable<CommentInfor>().Select(i => new CommentInfor
          {
             UID = i.UID.SelectAll(),
             ReplyToUser = i.ReplyToUID > 0 ? i.ReplyToUID.GetConfigValue<UserInfor>() : null,
             Commenter = i.UID.GetConfigValue<UserInfor>()
          })
          var data = db.Queryable<CommentInfor>()
          .Where(i => i.ArticleID == articleID).Take(10)
          .ToTree(i => i.Replies, i => i.ParentID, 0); //此处返回了全部符合条件的记录,如何限制只返回前5条记录呢?
          return new ListResult<CommentInfor>(data);
        }


    0 回复
  • Select(xxx)

    .MergeTable()

    .Includes() 是可以这样的 你的DTO需要配置导航,并且DTO中配置导航的字段要有值

    0 回复
  • yookt yookt VIP0
    2024/2/6

    @fate sta:大佬,Select中的代码如何写呢?能否详细一点,万分感谢!

    0 回复
  •     var data = db.Queryable<CommentInfor>().Select(i => new CommentInfor
          {
             UID = i.UID.SelectAll(),
             ReplyToUser = i.ReplyToUID > 0 ? i.ReplyToUID.GetConfigValue<UserInfor>() : null,
             Commenter = i.UID.GetConfigValue<UserInfor>()

          })

           .MergeTable()

          .Includes(x=>x.Child.Take(10).ToList(),x=>x.Child.Take(10).ToList(),x=>x.Child.Take(10).ToList())

         .ToList();


    0 回复
  • 差不多这个意思

    DTO配置好导航

    0 回复
  • yookt yookt VIP0
    2024/2/7

    @fate sta:谢谢大佬,您给的代码是可以实现限定读取条数,但是有个问题,我的DTO中是有通过UID读取用户昵称的配置的,Include后在Replies列表中用户昵称获取不到了,请问该如何修改呢?

    image.png

    image.png

    0 回复
  • image.png

    不就是这么写的吗?

    0 回复
  • yookt yookt VIP0
    2024/2/7

    @fate sta

    我的意思是Replies中也有commenter这个字段,需要通过配置查询来关联到用户名字段,而Replies是通过一对多导航查询出的数据

    image.png

    所以我想请教,在Includes方法中能否实现配置查询。我现在用的是笨办法,首先查询出评论列表,然后循环每个评论来分别读取相应的回复,但这样会多次读取数据库。

    image.png


    0 回复
  • @yookt:用导航就可以实现

    0 回复
  • 一对一导航

    0 回复
  • 不要想着联表了,返回一个对象就行了

    0 回复