3

私は最初にEFコードを使用していますが、特定の列(ここではSeniority)に基づいてプレーヤーのランクを取得するクエリを作成しようとしています。ここ
は(Rankはそれの一部ではない、私はSeniorityからそれを推測する必要があります)Playersテーブル何ができるかの例です:エンティティへの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まで)、これを改ページします。 1ページあたり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.IGroup 2[System.Int32,Models.BO.Players.Player],System.Int32,System.Collections.Generic.IEnumerable 1 [Models.BO.Ranking.PlayerRanking]]]) 'このメソッドをストア式に変換することはできません。

私はEF 2つの引数を持つWhereSelectMany文句を言っていることをいくつかの他の記事で読むが、私はせずに何ができますか?
ToList()AsEnumerable()を使用したくないのですが、もし私が要求すれば、要求はすべてPlayersのエントリを列挙してくれるはずです。私はこの特定のクエリのパフォーマンスについて本当に気にしています。

方法はありますか?

ありがとうございます。

@octavioccl

私はちょうどページネーションのためのSkip一部を追加しました: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するplayer1を持っている:)
しかし、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'節についてはわかりませんでしたが、実際にはかなり涼しくて、必要ならば間違いなく使用します!アプリは実際のユーザーがいないので、私はパフォーマンスについては確信することはできませんが、少なくとも私は開発中にそれについて考えようとします。これはこの質問に直接リンクされていないかもしれませんが、本当にありがとうと言いたいのは、あなたが私を含めて多くの時間を過ごすためです。 –

関連する問題