3

먼저 EF 코드를 사용하고 있는데 특정 열 (여기서는 Seniority)을 기반으로 플레이어의 순위를 얻는 쿼리를 작성하려고합니다.
여기 가 Players 테이블이 될 수 있는지의 예입니다 (Rank 그것의 일부가 아닌, 내가 Seniority에서 추론 할 필요) :엔티티에 Linq가있는 IGrouping 인덱스를 얻는 방법은 무엇입니까? (NotSupportedException)

Username | Seniority (=> Rank) 
player1 | 25  (=> 1st) 
player2 | 20  (=> 2nd) 
player3 | 20  (=> 2nd) 
player4 | 18  (=> 3rd) 
player5 | 16  (=> 4th) 
player6 | 16  (=> 4th) 
player7 | 15  (=> 5th) 
player8 | 11  (=> 6th) 
player9 | 10  (=> 7th) 
player10 | 8   (=> 8th) 
player11 | 7   (=> 9th) 
player12 | 5   (=> 10th) 
player13 | 2   (=> 11th) 
player14 | 1   (=> 12th) 
player15 | 0   (=> 13th) 

내가 누구의 순위 모든 선수를 반환하는 다음과 같은 요청을해야합니다 < = 10 (즉, player1에서 player12까지) 다음 페이지 매기기; 예를 들어 페이지 당 최대 10 개의 요소 (즉, player1에서 player10까지)가있는 첫 번째 페이지입니다. 방법 'System.Linq.IQueryable 1[Models.BO.Ranking.PlayerRanking] SelectMany[IGrouping 2 PlayerRanking (System.Linq.IQueryable 1[System.Linq.IGrouping 인식하지 않는 엔티티

entities.Players 
.GroupBy(p => p.Seniority) 
.Where((group, groupIndex) => groupIndex <= 10) 
.SelectMany((group, groupIndex) => 
    group.Select(grp => 
     new PlayerRanking() 
     { 
      Player = grp, 
      Rank = groupIndex + 1, 
      Score = grp.Seniority 
     } 
    ) 
    .OrderByDescending(r => r.Score) 
    .ThenBy(r => r.Player.UserName) 
) 
.ToPagedList(pageNb, 10); 

LINQ 2 선택 System.Int32, Models.BO.Players.Player] , System.Linq.Expressions.Expression 1[System.Func 3 [System.Linq.IGrouping 2[System.Int32,Models.BO.Players.Player],System.Int32,System.Collections.Generic.IEnumerable 1 [Models.BO.Ranking.PlayerRanking]]]) '이 메서드를 저장소 식으로 변환 할 수 없습니다.

나는 EF에 대한 Where 두 개의 인자를 가진 SelectMany을 불평 몇 가지 다른 게시물에 읽고,하지만 난없이 할 수 있을까?
내가하는 경우 ToList() 또는 AsEnumerable()을 사용하고 싶지 않습니다. 요청이 모두 Players 항목을 열거 할 것 같아요. 나는이 특별한 쿼리에 대한 공연에 정말로 관심이있다.

방법이 있습니까?

고마워요. pageNb = 1를 들어, 결과가 올 것 같다

var result = entities.Players.GroupBy(p => p.Seniority) 
         .OrderBy(e=>e.Key) 
         .Skip((pageNb - 1) * 10) 
         .Take(10) 
         .AsEnumerable() 
         .SelectMany((g,i)=>g.OrderBy(e=>e.UserName) 
              .Select(e=>new PlayerRanking() 
                 { 
                  Player = e, 
                  Rank = i + 1, 
                  Score = e.Seniority 
                 }); 

, 내가 올바른 계급 :
와 player10하는 재생기가 있습니다

@octavioccl

난 그냥 페이지 매김을위한 Skip 부분을 추가 그러나 pageNb = 2의 경우 순위가 다시 1에서 다시 시작됩니다 (즉, player11은 9 대신 1로 표시됨).

답변

2

Linq to Entities는 index으로 메소드 오버로드를 지원하지 않습니다. 또한 GroupBy 시퀀스를 반환하기 때문에 (단순히 SQL + GROUP BY의 키 + 집계가 아니라) 생성 된 SQL에서 2 개의 테이블 액세스 경로가 생기므로이를 수동으로 수행하고 Count 방법을 사용하여 순위를 결정할 수 있습니다 뚜렷한 Seniority 값은 현재 값보다 큽니다.

그래서 쿼리의 작업 상응하는 같은 수 :

var result = entities.Players 
    .Select(p => new PlayerRanking 
    { 
     Player = p, 
     Rank = entities.Players.Where(p1 => p1.Seniority > p.Seniority) 
       .Select(p1 => p1.Seniority).Distinct().Count() + 1, 
     Score = p.Seniority 
    }) 
    .Where(r => r.Rank <= 10) 
    .OrderBy(r => r.Rank) 
    .ThenBy(r => r.Player.UserName) 
    .ToPagedList(pageNb, 10); 
+0

고마워, 매력처럼 작동합니다! 한 번 더, 당신은 내 하루를 만들었고 어떤 것을 배웠습니다 : D –

+0

당신은 천만에요. 모든 질문은 흥미롭고 도전적입니다 :) 불행히도 SQL [OVER'] (https://msdn.microsoft.com/en-us/library/ms189461)을 이길 수는 없습니다.aspx) 절을 사용하지만 단순히 LINQ/EF 구성 요소는 없습니다. 성능 문제가있는 경우 원시 SQL에 의지 할 수 있습니다. –

+2

'OVER' 조항에 대해 알지 못했지만 참으로 멋진 것 같습니다. 필요한 경우 확실히 사용할 것입니다! 앱에는 실제 사용자가 없기 때문에 퍼포먼스에 대해서는 확신 할 수 없지만 적어도 개발 중에는 그것에 대해 생각하려고합니다. 이것이이 질문에 직접적으로 연결되어 있지는 않지만, 저를 비롯한 많은 사람들을 돕기 위해 많은 시간을 보냅니다. 감사합니다.) –

관련 문제