我有一个包含以下实体的模型:
Game: Id
User: Id
UserRating: Id, UserId, GameId, Value
用户可以为游戏评分。
我希望有一个查询可以返回评分最高的前5个游戏。最高评级应基于价值,但如果有2个或更多具有相同评级的游戏,则还应考虑计数。
如何在查询中表达这一点,使用lambda表达式将结果列表作为Game实体返回?
(使用EF 4,MVC,SQL Server)。
答案 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);