2011-01-09 3 views
2

현재 포럼을 개발 중입니다. 나는 LINQ와 EF를 처음 사용합니다. 저의 포럼에는 가장 최근 주제가있는 주제의 목록을 먼저 보여주는 디스플레이가 있습니다.LINQ to Entities orderby 및 null 모음에 대한 질문

"가장 최근"은 주제 응답과 관련이 있습니다. 따라서 주제의 게시 날짜별로 목록을 정렬하고 싶지는 않지만 주제의 마지막 회신 게시 날짜로 목록을 정렬하고 싶습니다. 따라서 새로운 답변이 포함 된 주제가 목록의 맨 위로 나타납니다. 모든 주제가 적어도 하나의 답을 가지고 있다는 것을 알았다면 이것은 다소 간단합니다. 나는 단지 이것을 할 것이다 :

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

그러나 많은 경우 주제에 응답이 없다. 어떤 경우에는 주제의 게시 날짜를 대신 사용하고 싶습니다. 항목에 응답이없는 경우 x.PostedDate을 주문하는 방법이 내 linq 쿼리 내에 있습니까? 나는 이것으로 혼란스러워하고 어떤 도움을 주시면 감사하겠습니다. 위의 쿼리를 사용하면 회신이 있다고 가정하는 x.Replies.Last() 때문에 회신이없는 주제가 나옵니다. LastOrDefault()은 응답이 있다고 가정하는 PostedDate 속성에 액세스해야하므로 작동하지 않습니다.

사전 통찰력에 감사드립니다.

+0

아마도 모든 답장을 받고, 반복하면서 if 문을 사용하여 응답이 있는지 확인하고 그런 식으로 새 목록을 작성하면됩니다. 그러나 질의 내에서 그것을 수행하고 매번 반복하지 않는 방법이 있다면 그것은 훌륭 할 것입니다. – Chev

답변

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

편집 :

가 귀하의 코멘트에 대답하기 위해, 더는 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); 
+0

나는 당신을 사랑합니다. 너는 나에게 많은 시간을 구해줬다. 나는 몰랐다.()와 '고맙다.'+1하고 시간이 올 때 받아 들여서 나를 용납한다. – Chev

+0

도움이 되었다니 다행이다. –

+0

chain linq에서 let 키워드를 어떻게 사용하는지 예제를 제공 할 수 있을까? '.OrderBy (x => x.PostedDate) '와 비슷합니다. – Chev

0

주제 데이터에 새 필드를 추가 하시겠습니까? LastActivityDate와 같은 것입니다. 처음에 주제로 설정 한 후 회신이 추가 될 때마다 업데이트됩니다.

저는 SQL Server 전문가는 아니지만 쿼리를 요청할 경우 색인을 무시하고 전체 테이블 검색을 수행하는 쿼리로 끝날 수 있습니다.

+0

실제로 인라인 SQL 쿼리를 사용하여 이전 사이트에서 사용한 방법입니다. . 나는 그것이 중복 된 것처럼 느꼈고 위의 대답 덕분에 그것을 대체 할 수 있습니다. – Chev

+0

이것은 또한 응답이 작성되었을 때이 새로운 응답 필드를 응답 시간으로 갱신하고 주제가 목록의 맨 위에 올 것임을의 L합니다. 그러나 사용자가 그 답장을 삭제하면 어떻게 될까? 이전 회신 시간으로 되돌릴 수있는 쉬운 방법은 없습니다. 나는 지금하고있는 것처럼 마지막 답장을 읽어야 할 것이다. 마지막 게시물 IMHO를 기반으로 응답 시간을 동적으로 유지하는 것이 좋습니다. – Chev

2

댓글을 달 수 없습니다. 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.OrderByDesc(r => r.PostedDate).First().PostedDate 
+0

예, 아주 좋습니다. 멋지다. – Chev

+0

지금 댓글을 달 수 있어야합니다 ..;) – NotMe

+0

@Chris, Yee-hooo, 여기 있어요. – Joker

0

전형적인 포럼 특히이 특정한 경우에, 읽고 몇 쓰기 많은있다

x.Replies.Last().PostedDate 

변경할 수 있습니다. 따라서 LastPostDate를 추가 필드에 캐시하도록 선택합니다. 가치를 최신으로 유지하기 위해 약간의 중복성과 약간의 프로그래밍을 제공하지만, 대부분의 경우 그것이 최선의 방법이라고 생각합니다.

+0

참이지만 각 회신과 함께 추가로 작성됩니다. 또한, LINQ와 게으른로드로 나는 마지막 답신 날짜를 잡는 것이 더 효율적이라고 믿습니다. 동일한 수의 읽기, 하나의 쓰기가 적습니다. – Chev

관련 문제