最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - The LINQ expression could not be translated when using MaxBy - Stack Overflow

programmeradmin6浏览0评论

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
  • 1 Which DBMS do you target? – Klaus Gütter Commented Feb 10 at 9:09
  • 1 .OrderBy(...).Take(1) instead works? – Fildor Commented Feb 10 at 9:10
  • @KlausGütter Postgres – lonix Commented Feb 10 at 9:11
  • 3 The duplicates both mention OrderByDescending(..).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:37
  • 1 What GH issue do you refer to? A common way to return 1 inner row per outer row is to use SELECT NAME From Files Where Files.UserID=outer.ID ORDER BY Created Desc LIMIT 1. The LINQ equivalent is OrderByDescending(..).FirstOrDefault(). That's what the duplicates show. If you started from Users instead of Files you could write context.Users.ToDictionary(x=>x.Id,x=>x.Files.OrderBy.....) directly. – Panagiotis Kanavos Commented Feb 10 at 12:54
 |  Show 6 more comments

1 Answer 1

Reset to default 0

Thanks 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.

发布评论

评论列表(0)

  1. 暂无评论