2011-09-03 143 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(); 
相关问题