LINQ如何获得最大评级

时间:2013-03-28 11:11:45

标签: linq linq-to-entities

我有一个包含以下实体的模型:

Game: Id
User: Id
UserRating: Id, UserId, GameId, Value

用户可以为游戏评分。

我希望有一个查询可以返回评分最高的前5个游戏。最高评级应基于价值,但如果有2个或更多具有相同评级的游戏,则还应考虑计数。

如何在查询中表达这一点,使用lambda表达式将结果列表作为Game实体返回?

(使用EF 4,MVC,SQL Server)。

1 个答案:

答案 0 :(得分:2)

我认为“最高评级”是指“最高平均评分”?这听起来像你想要的东西:

var query = from rating in db.UserRating
            group rating by rating.GameId into ratings
            orderby ratings.Average(x => x.Value) descending,
                    ratings.Count() descending
            join game in db.Game on ratings.Key equals game.Id
            select game;

var top5Games = query.Take(5);

编辑:在非查询表达形式中,这将更加痛苦,但仍然可行:

var top5Games = db.UserRating
                  .GroupBy(rating => rating.GameId)
                  .OrderByDescending(ratings => ratings.Average(x => x.Value))
                  .ThenByDescending(ratings => ratings.Count())
                  .Join(db.Game, r => r.Key, g => g.Id, (r, g) => g)
                  .Take(5);

在这种情况下,在lambda语法中执行它不会坏,因为你只是让游戏退出连接......但更一般地说,它变得更糟糕。绝对值得理解并使用这两种形式,这取决于哪种方法对于手头的查询更简单。特别是,当你开始进行多个连接时,它在lambda语法中变成了可怕的

请注意,这不会给出该游戏的评分...为此,您可能需要以下内容:

select new { Game = game,
             RatingAverage = ratings.Average(x => x.Value),
             RatingCount = ratings.Count() }

在查询结束时而不仅仅是select game

另请注意,可能想要排除目前没有足够评分的游戏才有意义 - 否则一个评分为“完美”的游戏将始终位于顶部

编辑:好的,在“游戏名称”的最终抢七局中,我肯定会使用查询表达形式:

var query = from rating in db.UserRating
            join game in db.Game on ratings.Key equals game.Id
            select new { rating, game } into pair
            group pair by pair.game into pairs
            orderby pairs.Average(x => x.rating.Value) descending,
                    pairs.Count() descending,
                    pairs.Key.Name
            select pairs.Key;

var top5Games = query.Take(5);