选择父项时对子实体进行排序

时间:2011-06-06 13:42:05

标签: entity-framework linq-to-sql lambda

我有这些课程:

public class WallPost
    {
        public long WallPostId { get; set; }

        [Required]
        public long UserId { get; set; }
        [Required]
        public long WallUserId { get; set; }
        [Required]
        public string PostText { get; set; }
        public DateTime CreatedOn { get; set; }

        public virtual User WallUser { get; set; }
        public virtual User User { get; set; }
        public virtual ICollection<WallPostReply> WallPostReplies { get; set; }

    }

 public class WallPostReply
    {
        [Key]
        public long ReplyId { get; set; }

        [Required]
        public long UserId { get; set; }
        [Required]
        public long WallPostId { get; set; }
        [Required]
        public string ReplyText { get; set; }
        [Required]
        public DateTime CreatedOn { get; set; }


        public virtual WallPost WallPost { get; set; }
        public virtual User User { get; set; }
    }

在一种方法中,我获得了按CreatedOn排序的所有墙贴:

public IEnumerable<WallPost> GetMorePosts(long wallUserId, int pageNumber, bool showOnlyMyPosts)
        {   
            var wallUser = _db.Users.Where(x => x.UserId == wallUserId).FirstOrDefault();
            var postEntries = wallUser.MyWallPosts.Where(x => x.UserId == wallUser.UserId || showOnlyMyPosts == false).OrderByDescending(x => x.CreatedOn)
                .Skip(5 * pageNumber).Take(5);

            return postEntries;
        }

我想要做的是获取按CreatedOn排序的WallPostReplies子实体,如何在同一个查询中编写它?

2 个答案:

答案 0 :(得分:2)

首先,您的第二个查询是linq-to-objects,而不是linq-to-entities - 它将始终加载所有用户的帖子,并在您的应用程序服务器上进行过滤和排序。接下来,您不会显式加载回复,因此一旦您开始浏览它们,您将为每个帖子设置单独的延迟加载查询=&gt; N + 1问题。

使用linq-to-entities加载数据时,无法直接对子实体进行排序。您必须将投影用于匿名类型:

var query = _db.WallPosts
               .Where(x => x.UserId == userId)
               .OrderByDescending(x => x.CreatedOn)
               .Skip(5 * pageNumber)
               .Take(5);
               .Select(x => new 
                   {
                      Post = x,
                      Replies = x.WallPostReplies.OrderBy(y => y.CreatedOn)
                   });

再试一次:您无法从linq-to-entities获取具有已排序相关实体(WallPosts)的WallReplies个实例。您必须在linq-to-objects中对WallPosts进行投影:

IEnumerable<WallPosts> posts = query.AsEnumerable()
                                    .Select(x => new WallPost
                                        {
                                            WallPostId = x.Post.WallPostId,
                                            UserId = x.Post.UserId,
                                            WallUserId = x.Post.WallUserId,
                                            PostText = x.Post.PostText,
                                            CreatedOn = x.Post.CreatedOn,
                                            Replies = x.Replies
                                        });

答案 1 :(得分:1)

我有一个类似的问题.. 如果我理解你的话,你首先需要一个帖子列表,然后为每个帖子想要一份回复列表吗?

首先我们得到有问题的帖子......

//gets posts ... 
public IEnumerable<WallPost> GetMorePosts(long wallUserId, int pageNumber, bool showOnlyMyPosts)         {                
    WallUser wallUser = _db.Users.Where(x => x.UserId == wallUserId).FirstOrDefault() as WallUser;             
    IEnumerable<WallPost> results = 
       (from post in wallUser.MyWallPosts where post.UserId == wallUser.UserId  showOnlyMyPosts == false order by post.CreatedOn descending)
         .Skip(5 * pageNumber)
         .Take(5);              

    return results.ToList();         
    } 

然后我们得到回复......

// gets replies

IEnumerable<WallPost> posts = GetMorePosts(userid, pageNo, showonlyMine);
foreach(WallPost post in posts)
{
  IEnumerable<WallPostReply> replies = (from reply in post.WallPostReplies order by reply.CreatedOn select reply).ToList();
  // do something with post and the order list of replies
}  

简而言之......我的建议......不要试图立刻做太多事!