LINQ To Entities does not recognize the method Last. Really?

C#Entity FrameworkOrm

C# Problem Overview


In this query:

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());
}

I had to switch it to this for it to work

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());
}

I couldn't even use p.First(), to mirror the first query.

Why are there such basic limitations in what's otherwise such a robust ORM system?

C# Solutions


Solution 1 - C#

That limitation comes down to the fact that eventually it has to translate that query to SQL and SQL has a SELECT TOP (in T-SQL) but not a SELECT BOTTOM (no such thing).

There is an easy way around it though, just order descending and then do a First(), which is what you did.

EDIT: Other providers will possibly have different implementations of SELECT TOP 1, on Oracle it would probably be something more like WHERE ROWNUM = 1

EDIT:

Another less efficient alternative - I DO NOT recommend this! - is to call .ToList() on your data before .Last(), which will immediately execute the LINQ To Entities Expression that has been built up to that point, and then your .Last() will work, because at that point the .Last() is effectively executed in the context of a LINQ to Objects Expression instead. (And as you pointed out, it could bring back thousands of records and waste loads of CPU materialising objects that will never get used)

Again, I would not recommend doing this second, but it does help illustrate the difference between where and when the LINQ expression is executed.

Solution 2 - C#

Instead of Last(), Try this:

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

Solution 3 - C#

Replace Last() by a Linq selector OrderByDescending(x => x.ID).Take(1).Single()

Something like that would be works if you prefert do it in 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());
}

Solution 4 - C#

Yet another way get last element without OrderByDescending and load all entities:

dbSet
    .Where(f => f.Id == dbSet.Max(f2 => f2.Id))
    .FirstOrDefault();

Solution 5 - C#

That's because LINQ to Entities (and databases in general) does not support all the LINQ methods (see here for details: http://msdn.microsoft.com/en-us/library/bb738550.aspx)

What you need here is to order your data in such a way that the "last" record becomes "first" and then you can use FirstOrDefault. Note that databasese usually don't have such concepts as "first" and "last", it's not like the most recently inserted record will be "last" in the table.

This method can solve your problem

db.databaseTable.OrderByDescending(obj => obj.Id).FirstOrDefault();

Solution 6 - C#

Adding a single function AsEnumerable() before Select function worked for me.
Example:

return context.ServerOnlineCharacters
    .OrderByDescending(p => p.ServerStatus.ServerDateTime)
    .GroupBy(p => p.RawName).AsEnumerable()
    .Select(p => p.FirstOrDefault());

Ref: https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbevacquaView Question on Stackoverflow
Solution 1 - C#Neil FenwickView Answer on Stackoverflow
Solution 2 - C#AzarsaView Answer on Stackoverflow
Solution 3 - C#Ema.HView Answer on Stackoverflow
Solution 4 - C#Stas BoyarincevView Answer on Stackoverflow
Solution 5 - C#Mohammad HassaniView Answer on Stackoverflow
Solution 6 - C#Artem LevitinView Answer on Stackoverflow