2013-03-28 78 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