Сортировка дочерних объектов при выборе родителей - PullRequest
1 голос
/ 06 июня 2011

У меня есть эти классы:

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;
        }

Что я хочу сделать, так это получить также WallPostRepliesДочерние сущности также отсортированы по CreatedOn, как написать это в том же запросе?

Ответы [ 2 ]

2 голосов
/ 06 июня 2011

Прежде всего, ваш второй запрос - это linq-to-objects, а не linq-to-entity - он всегда будет загружать сообщения всех пользователей и выполнять фильтрацию и упорядочивание на вашем сервере приложений. Далее вы явно не загружаете ответы, поэтому, как только вы начнете просматривать их, у вас будет отдельный ленивый загрузочный запрос для каждой проблемы post => N + 1.

Невозможно напрямую отсортировать дочерние объекты при загрузке данных с linq-to-entity. Вы должны использовать проекцию на анонимный тип:

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)
                   });

Итак, еще одна попытка: вы не можете получить WallPosts экземпляров с отсортированными связанными сущностями (WallReplies) от linq-to-entity. Вы должны сделать проекцию на WallPosts в linq-to-objects:

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 голос
/ 07 июля 2011

В какой-то момент у меня была похожая проблема. Если я вас правильно понял, вы сначала хотите получить список сообщений, а затем для каждого сообщения вы хотите получить список ответов?

Итак, сначала мы получаем сообщения ввопрос ...

//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
}  

Короче ... мой совет ... не пытайтесь делать слишком много сразу!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...