在此查询中:
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 :(得分:203)
这种限制归结为最终它必须将该查询转换为 SQL 而SQL具有SELECT TOP
(在T-SQL中)而不是SELECT BOTTOM
(没有这样的事情)。
虽然有一种简单的方法,只需降序,然后执行First()
,这就是你所做的。
修改强>
其他提供者可能会有SELECT TOP 1
的不同实现,在Oracle上它可能更像WHERE ROWNUM = 1
修改强>
另一种效率较低的替代方案 - 我不建议这样做! - 是在.ToList()
之前调用数据.Last()
,这将立即执行LINQ To Entities Expression已构建到那一点,然后你的.Last()将起作用,因为此时.Last()
有效地在 LINQ to Objects 表达式的上下文中执行。 (正如你所指出的那样,它可以带回数以千计的记录并浪费大量的CPU实现永远不会被使用的对象)
同样,我不建议这样做,但它确实有助于说明执行LINQ表达式的位置和时间之间的区别。
答案 1 :(得分:30)
取代Last()
,试试这个:
model.OrderByDescending(o => o.Id).FirstOrDefault();
答案 2 :(得分:14)
将Linq选择器Last()
OrderByDescending(x => x.ID).Take(1).Single()
如果您在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());
}
答案 3 :(得分:0)
另一种方法是获取没有OrderByDescending的最后一个元素并加载所有实体:
dbSet
.Where(f => f.Id == dbSet.Max(f2 => f2.Id))
.FirstOrDefault();
答案 4 :(得分:0)
这是因为LINQ to Entities(和一般的数据库)不支持所有LINQ方法(有关详细信息,请参见此处:http://msdn.microsoft.com/en-us/library/bb738550.aspx)
这里您需要的是对数据进行排序,以使“最后”记录变为“第一”,然后可以使用FirstOrDefault。请注意,databasese通常没有诸如“ first”和“ last”之类的概念,这与表中最近插入的记录不是“ last”一样。
这种方法可以解决您的问题
db.databaseTable.OrderByDescending(obj => obj.Id).FirstOrDefault();
答案 5 :(得分:-2)
在Select函数对我有用之前,添加一个函数AsEnumerable()
。
示例:
return context.ServerOnlineCharacters
.OrderByDescending(p => p.ServerStatus.ServerDateTime)
.GroupBy(p => p.RawName).AsEnumerable()
.Select(p => p.FirstOrDefault());
参考: https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys