我有一个包含以下实体的模型:
Game: Id
User: Id
UserRating: Id, UserId, GameId, Value
用户可以给游戏评分。
我想要一个查询,返回评分最高的前 5 场比赛。最高评分应以Value为基础,但当有2个或更多游戏具有相同评分时,还应考虑计数。
如何在查询中表达这一点,使用 lambda 表达式将结果列表作为游戏实体返回?
(使用 EF 4、MVC、SQL Server)。
我有一个包含以下实体的模型:
Game: Id
User: Id
UserRating: Id, UserId, GameId, Value
用户可以给游戏评分。
我想要一个查询,返回评分最高的前 5 场比赛。最高评分应以Value为基础,但当有2个或更多游戏具有相同评分时,还应考虑计数。
如何在查询中表达这一点,使用 lambda 表达式将结果列表作为游戏实体返回?
(使用 EF 4、MVC、SQL Server)。
我假设“最高评分”是指“最高平均评分”?听起来你想要这样的东西:
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);