LINQ to Entities вопрос о коллекциях orderby и null - PullRequest
2 голосов
/ 09 января 2011

Я сейчас занимаюсь разработкой форума.Я новичок в LINQ и EF.У меня на форуме есть экран, который показывает список тем с самыми новыми темами в первую очередь.

Проблема в том, что «самые последние» относятся к ответам на темы.Поэтому я не хочу упорядочивать список по дате публикации темы, а хочу упорядочить список по дате публикации последнего ответа в теме.Так что темы с новыми ответами всплывают обратно в начало списка.Это довольно просто, если бы я знал, что у каждой темы есть хотя бы один ответ;Я бы просто сделал это:

var topicsQuery = from x in board.Topics
                  orderby x.Replies.Last().PostedDate descending
                  select x;

Однако во многих случаях тема не имеет ответов.В этом случае я бы хотел использовать дату публикации темы.Есть ли способ в моем запросе linq упорядочить по x.PostedDate, если в теме нет ответов?Я смущен этим, и любая помощь будет оценена.С помощью приведенного выше запроса он разбивается на темы без ответов, поскольку x.Replies.Last() предполагает, что ответы есть.LastOrDefault() не работает, потому что мне нужен доступ к свойству PostedDate, в котором также предполагается, что ответ существует.

Заранее благодарим вас за понимание.

Ответы [ 4 ]

7 голосов
/ 09 января 2011
var topicsQuery = from x in board.Topics
                  let lastActivityDate = x.Replies.Any() 
                         ? x.Replies.Last().PostedDate 
                         : x.PostedDate
                  orderby lastActivityDate descending
                  select x;

Edit:

Чтобы ответить на ваш комментарий, в синтаксисе выражения linq явно не указано . Но вы можете добиться того же, как показано ниже (используя промежуточное выражение выбора):

var topicsQuery = board.Topics.Select(x => new { 
                                                  Topic = x, 
                                                  LastActivityDate = x.Replies.Any() 
                                                      ? x.Replies.Last().PostedDate 
                                                      : x.PostedDate
                                    })
                             .OrderByDescending(p => p.LastActivityDate)
                             .Select(r => r.Topic)

Edit2:

Это можно еще больше упростить, как предлагал Николас, мы также можем удалить промежуточный оператор выбора. Обратите внимание, что это было бы невозможно, если бы не различное исполнение.

var topicsQuery = board.Topics
        .OrderByDescending(x => x.Replies.Any() 
                                      ? x.Replies.Last().PostedDate 
                                      : x.PostedDate);
2 голосов
/ 09 января 2011

комментировать не могу. FWIW, рассматривать это как комментарий.

var topicsQuery = from x in board.Topics
              let lastActivityDate = x.Replies.Any() 
                     ? x.Replies.Last().PostedDate 
                     : x.PostedDate
              orderby lastActivityDate descending
              select x;

Возможно, вы захотите изменить

x.Replies.Last().PostedDate 

это

x.Replies.OrderByDesc( r => r.PostedDate).First().PostedDate
0 голосов
/ 09 января 2011

Типичный форум имеет много чтения и мало записей, особенно в этом конкретном случае.Поэтому я бы выбрал кэширование LastPostDate в дополнительном поле.Это дает некоторую избыточность и немного больше программирования для поддержания актуальности, но я думаю, что в большинстве случаев это лучший способ.

0 голосов
/ 09 января 2011

Задумывались ли вы о добавлении нового поля в ваши данные Темы? Что-то вроде LastActivityDate. Установите его в соответствии с темами PostedDate, а затем обновляйте каждый раз, когда добавляется ответ.

Я не эксперт по SQL Server, но если вы попытаетесь выполнить то, что вы просите, с помощью запроса, вы, вероятно, получите запрос, который будет игнорировать ваши индексы и выполнять полное сканирование таблицы.

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