2011-09-03 144 views
111

在此查詢:LINQ To Entities不識別方法Last。真?

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters 
     .OrderBy(p => p.ServerStatus.ServerDateTime) 
     .GroupBy(p => p.RawName) 
     .Select(p => p.Last()); 
} 

我不得不切換到這個爲它工作

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters 
     .OrderByDescending(p => p.ServerStatus.ServerDateTime) 
     .GroupBy(p => p.RawName) 
     .Select(p => p.FirstOrDefault()); 
} 

我甚至不能使用p.First(),以反映第一個查詢。

爲何會出現在什麼否則這樣一個強大的ORM系統,例如基本的限制?

+0

存儲區IEnumrable對象插入到一個新的變量,然後返回variable.last()。它會工作。 –

回答

174

這個限制歸結到最終它必須是翻譯查詢SQL事實和SQL有一個SELECT TOP(以T-SQL),但不是SELECT BOTTOM(沒有這樣的事情)。

雖然有一個簡單的方法,只是順序降然後做一個First(),這是你做的。

編輯: 其他供應商將可能有SELECT TOP 1不同的實現方式,在Oracle它很可能是更多的東西一樣WHERE ROWNUM = 1

編輯:

另一個不那麼有效的替代方案 - 我不推薦這個! - 是調用數據.ToList().Last()之前,將立即執行LINQ要想在已經建立起來的那點實體的表達,然後你的。去年()將工作,因爲在這一點上.Last()中有效執行而不是表達式。 (正如你指出的那樣,它可能會帶回成千上萬的記錄和浪費的CPU物化對象,永遠不會被使用)

同樣,我不會推薦這麼做,但它確實有助於說明在哪裏並執行LINQ表達式時。

+0

以及LINQ To SQL如何處理這種情況? – bevacqua

+1

@Nico:它也會拋出。 – jason

+0

@Neil是的,我知道我可以調用ToList,但我寧願不檢索成千上萬的從數據庫記錄只是將它們過濾到五個記錄 – bevacqua

12

通過一個LINQ選擇更換Last()OrderByDescending(x => x.ID).Take(1).Single()

喜歡的東西,這將是作品,如果你prefert Linq中做到這一點:

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters.OrderBy(p => p.ServerStatus.ServerDateTime).GroupBy(p => p.RawName).Select(p => p.OrderByDescending(x => x.Id).Take(1).Single()); 
} 
+0

這對我來說非常合適。 –

+1

是否有任何理由使用.Take(1).Single()而不是.FirstOrDefault()? –

+1

@TZZZ在這種情況下,有效的替換將是.First(),因爲如果項目計數不完全是1,則Single()拋出異常。 – MEMark

17

相反的Last(),試試這個:

model.OrderByDescending(o => o.Id).FirstOrDefault(); 
0

另一種方式是獲取沒有OrderByDescending的最後一個元素並加載所有實體:

dbSet 
    .Where(f => f.Id == dbSet.Max(f2 => f2.Id)) 
    .FirstOrDefault(); 
相關問題