2013-03-28 84 views
0

我有以下实体模型:LINQ如何获得最大的评级

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

用户可以给游戏的评级。

我想有一个返回的前5场比赛的最高评级的查询。最高评分应该以价值为基础,但是如果有2个或更多的评分相同的游戏,则还应该考虑计数。

如何在查询中表达后,返回的结果列表,游戏实体,使用lambda表达式?

(使用EF 4,MVC,SQL服务器)。

回答

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语法中变成可怕的

注意,这不会给评级为那场比赛......得到的是,你可能想是这样的:在查询,而不是仅仅select game结束

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

另外请注意,您可能需要排除当前没有足够收视率的游戏才有意义 - 否则一个评分为“完美”的游戏将永远处于顶端。

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

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); 
+0

whow,快乔恩!这个查询是如何用C#LINQ语法风格表示的(aka .Join(x =>)? – 2013-03-28 11:16:56

+0

@PatrickPeters:为什么你需要这样做?这样做会很痛苦......可能,但是很痛苦,你应该总是使用任何一个形式将更具可读性,在这种情况下将是查询表达式形式 – 2013-03-28 11:17:49

+0

我想你是对有;-) – 2013-03-28 11:18:29