2011-12-26 53 views
0

,我發現了錯誤:LINQ的不支持轉換爲SQL

Method 'System.Decimal getMeanRatingForGame(Int32)' has no supported translation to SQL.

對於LINQ線:

let R = getMeanRatingForGame(c.ID) 

這裏的LINQ全:

private static Game[] getTopRatedGamesDo(int Fetch, int CategoryID, int Skip) 
{ 
    /** 
     weighted rating (WR) = ((v ÷ (v+m)) × R + (m ÷ (v+m)) × C) x E 
     where: 
     R = average for the game 
     v = number of votes for the game 
     m = minimum votes required to be listed 
     C = the mean weighted vote across the whole report 
     E = Is not example game (example game = 0, not example = 1) 
    */ 
    Game[] r; 
    using (MainContext db = new MainContext()) 
    { 
     // Mean 
     decimal C = getMeanRatingForCat(CategoryID); 

     // Min votes to be considered 
     decimal m = Settings.GameVotesReqdForTopRatedBoards; 

     // Entire games list 
     if (CategoryID == 0) 
     { 
      var q = (from c in db.tblArcadeGames 
         let v = (decimal)db.tblArcadeGameVotes.Where(v => v.GameID == c.ID).Count() 
         let R = getMeanRatingForGame(c.ID) 
         let E = (c.CategoryID == 2 ? (decimal)0.1 : (decimal)1) 
         let WR = (((v/(v + m)) * R + (m/(v + m)) * C) * E) 
         where c.IsDeleted == false 
         && c.Approved == true 
         && c.TotalVotes >= Settings.GameVotesReqdForTopRatedBoards 
         orderby WR descending 
         select new { c, WR}) 
       .Skip(Skip) 
       .Take(Fetch); 

      r = new Game[q.Count()]; 
      int i = 0; 
      foreach (var g in q) 
      { 
       r[i] = new Game(g.c, g.WR); 
       i++; 
      } 
     } 

和這裏的拋出錯誤的函數:

/// <summary> 
/// Gets the mean rating of a game. 
/// </summary> 
public static decimal getMeanRatingForGame(int GameID) 
{ 
    /** 
    Try multiplying each voter's rating base 10 logarithm of the rep of the voter, 
     * then finding the weighted rating, then dividing by the mean of the base 10 logarithms 
     * of the reps of the voters. Change the base from 10 to something like 2 if you want heavier weighting. 
     * */ 
    decimal C = 0; 
    using (MainContext db = new MainContext()) 
    { 
     var q = (from c in db.tblArcadeGameVotes 
        where c.GameID == GameID 
       let UserWeighting = (decimal)Math.Log((double)db.tblProfiles.Where(u => u.UserID == c.UserID).Single().Reputation, 10) 
       let WeightedVote = UserWeighting * (decimal)c.Score 
       select new { UserWeighting, WeightedVote }); 

     decimal AverageUserWeighting = (decimal)q.Sum(c => c.UserWeighting)/(decimal)q.Count(); 
     decimal AverageWeightedVote = (decimal)q.Sum(c => c.WeightedVote)/(decimal)q.Count(); 

     C = AverageWeightedVote/AverageUserWeighting; 
    } 
    return C; 
} 

我不允許在像這樣的linq語句中使用函數嗎?

+0

您是如何期待*您的方法調用被轉換爲SQL? (不,你不能在LINQ to SQL中調用任意方法。) – 2011-12-26 19:04:27

+0

我只知道一半的答案,不,你不能引用那個特定的函數,因爲Linq-Sql解析器不知道如何翻譯它。話雖如此,我相信你可以重寫getMeanRatingForGame作爲表達式嵌入到原始的linq語句中。 – neouser99 2011-12-26 19:08:43

+0

@Jon謝謝我感到困惑,因爲它可以在'select new {...'中選擇它,但我明白現在的區別。 – 2011-12-26 19:26:36

回答

1

您正在達到抽象失效的地步。

LINQ提供程序從LINQ轉換爲底層數據存儲可以理解的東西(在本例中爲SQL)。你可以想象,SQL沒有getMeanRatingForGame函數,所以LINQ to SQL失敗(就像EF,LINQ to Oracle等等)。

一個解決方案是將您的查詢分解爲兩個(或更多)部分 - 一個只與SQL進行交互並且SQL不會有問題。

將結果與使用getMeanRatingForGame的另一個查詢結合使用 - 獲取LINQ to Objects以發揮其魔力。

+0

謝謝,如果我在'select new {...'中返回'WR'的所有組件,它就能正常工作。瞭解爲什麼它現在不起作用。 – 2011-12-26 19:22:34