Entities:
public class User
{
public long Id { get; }
public ICollection<File> Files { get; }
}
public class File
{
public long Id { get; }
public DateTime CreatedAt { get; }
public string Name { get; }
public User? User { get; } // nullable for other reasons
}
I want the name of the latest file for each user. I tried:
var data = await context
Files
.Where(x => x.User != null)
.GroupBy(x => x.User!.Id)
.Select(x => x.MaxBy(y => y.CreatedAt)!)
.ToDictionaryAsync(k => k.User.Id, v => v.Name);
But that throws
The LINQ expression ... could not be translated
I assume MaxBy
is unsupported (in EF Core 8).
Is there a workaround?
Entities:
public class User
{
public long Id { get; }
public ICollection<File> Files { get; }
}
public class File
{
public long Id { get; }
public DateTime CreatedAt { get; }
public string Name { get; }
public User? User { get; } // nullable for other reasons
}
I want the name of the latest file for each user. I tried:
var data = await context
Files
.Where(x => x.User != null)
.GroupBy(x => x.User!.Id)
.Select(x => x.MaxBy(y => y.CreatedAt)!)
.ToDictionaryAsync(k => k.User.Id, v => v.Name);
But that throws
The LINQ expression ... could not be translated
I assume MaxBy
is unsupported (in EF Core 8).
Is there a workaround?
Share Improve this question edited Feb 11 at 13:56 lonix asked Feb 10 at 9:07 lonixlonix 20.9k29 gold badges131 silver badges274 bronze badges 11 | Show 6 more comments1 Answer
Reset to default 0Thanks to the comment by @PanagiotisKanavos above, the simplest solution is:
await context
.Users
.Include(x => x.Files)
.Where(x => x.Files.Any())
.ToDictionaryAsync(
x => x.Id,
x => x.Files.OrderByDescending(y => y.CreatedAt).First().Name)
That completely avoids the MaxBy
issue.
Vote here for them to support it.
.OrderBy(...).Take(1)
instead works? – Fildor Commented Feb 10 at 9:10OrderByDescending(..).FirstOrDefault()
as an alternative. It shouldn't be hard to apply that to your model. Also, there are more questions asking for alternatives of MaxBy. – Gert Arnold Commented Feb 10 at 10:37SELECT NAME From Files Where Files.UserID=outer.ID ORDER BY Created Desc LIMIT 1
. The LINQ equivalent isOrderByDescending(..).FirstOrDefault()
. That's what the duplicates show. If you started fromUsers
instead ofFiles
you could writecontext.Users.ToDictionary(x=>x.Id,x=>x.Files.OrderBy.....)
directly. – Panagiotis Kanavos Commented Feb 10 at 12:54