如何使用Linq获取IGrouping索引到实体? (NotSupportedException异常)

时间:2017-03-04 11:50:10

标签: c# entity-framework linq linq-to-entities notsupportedexception

我首先使用EF代码,并且我尝试创建一个基于特定列获得玩家排名的查询,Seniority
以下是Players表格的示例(Rank不属于它,我需要从Seniority推断出来):

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个最大元素的第一页(即从播放器1到播放器10)。

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 to Entities无法识别方法&#39; System.Linq.IQueryable 1[Models.BO.Ranking.PlayerRanking] SelectMany[IGrouping 2,PlayerRanking](System.Linq.IQueryable 1[System.Linq.IGrouping 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]]])&#39;,这个方法无法转换为商店表达式。

我在其他一些帖子中看到EF抱怨WhereSelectMany有两个论点,但我可以不这样做吗。
我不想使用ToList()AsEnumerable(),因为如果我这样做,我猜这个请求将枚举所有Players条目(这可能真的很大......)虽然我只需要10个。我非常关心这个特定查询的表现。

有办法吗?

非常感谢。

@octavioccl

我刚刚添加Skip部分进行分页:

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

对于pageNb = 1,结果似乎是正确的,我有玩家1到玩家10的正确等级:) 但是对于pageNb = 2,Rank再次从1重新开始(即,player11被标记为1st而不是9)。

1 个答案:

答案 0 :(得分:2)

Linq to Entities不支持index的方法重载。此外,由于GroupBy返回序列的任何使用(而不仅仅是SQL GROUP BY中的键+聚合)导致生成的SQL中有2个表访问路径,您可以手动执行此操作并使用{{ 1}}确定排名的方法(应该是大于当前的不同Count值的计数)。

因此,查询的工作等价物可能是这样的:

Seniority