LINQ To Entities无法识别方法Last.真?

bev*_*qua 139 c# orm entity-framework

在此查询中:

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());
}
Run Code Online (Sandbox Code Playgroud)

我不得不把它切换到这个才能工作

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());
}
Run Code Online (Sandbox Code Playgroud)

我甚p.First()至无法使用镜像第一个查询.

为什么在这样一个强大的ORM系统中存在这样的基本限制?

Nei*_*ick 211

这种限制归结为最终它必须将该查询转换为SQL并且SQL具有SELECT TOP(在T-SQL中)而不是SELECT BOTTOM(没有这样的东西).

虽然有一个简单的方法,只需顺序下降,然后做一个First(),这就是你做的.

编辑: 其他提供商可能会有不同的实现SELECT TOP 1,在Oracle上它可能会更像WHERE ROWNUM = 1

编辑:

另一种效率较低的替代方案 - 我不建议这样做!- 之前是调用.ToList()你的数据.Last(),它会立即执行到那时为止构建的LINQ To Entities表达式,然后你的.Last()将会起作用,因为在那一点上.Last()它有效地执行了而是LINQ to Objects Expression.(正如你所指出的那样,它可能会带回数千条记录并浪费大量的CPU实现永远不会被使用的对象)

同样,我不建议这样做,但它确实有助于说明执行LINQ表达式的位置和时间之间的区别.

  • 如果你知道你的查询将返回小的结果,那么调用`ToList`并不是那么糟糕. (2认同)
  • 我想,如果您同意“作弊”并在 .NET 端执行此操作,那么您应该执行“.AsEnumerable().Last()”,而不是“.ToList().Last()”。如果您只想遍历整个源来获取最后一项,则无需在内存中增加一个大的“List&lt;&gt;”。 (2认同)

Aza*_*rsa 33

而不是Last(),试试这个:

model.OrderByDescending(o => o.Id).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)


Ema*_*a.H 14

Last()由Linq选择器替换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());
}
Run Code Online (Sandbox Code Playgroud)

  • @TotZam 在这种情况下,有效的替换将是 .First(),因为如果项目计数不完全是 1,Single() 会抛出异常。 (2认同)