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系统中存在这样的基本限制?
这个限制归结为这样一个事实,即最终必须将该查询翻译成SQL,并且SQL有一个SELECT TOP
(在T-SQL中),而不是SELECT BOTTOM
(没有这样的东西)。
有一个简单的方法,虽然,只是顺序降序 ,然后做一个First()
,这是你做的。
编辑:其他供应商可能会有不同的实施SELECT TOP 1
,在Oracle上它可能是更像WHERE ROWNUM = 1
编辑:
另一个效率较低的替代scheme – 我不推荐这个! – 在.Last()
.ToList()
之前调用.ToList()
,该.ToList()
将立即执行已经build立到该点的LINQ To Entities Expression,然后您的.Last()将会起作用,因为在那时.Last()
在LINQ to Objects Expression的上下文中被有效地执行。 (正如你所指出的,它可能会带回成千上万的logging,并浪费CPU的物质化对象永远不会被使用)
再一次,我不会推荐这么做,但它确实有助于说明LINQexpression式执行的时间和地点之间的区别。
而不是Last()
,试试这个:
model.OrderByDescending(o => o.Id).FirstOrDefault();
将Last()
replace为Linqselect器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()); }
另一种方式是获取没有OrderByDescending的最后一个元素并加载所有实体:
dbSet .Where(f => f.Id == dbSet.Max(f2 => f2.Id)) .FirstOrDefault();