【问题标题】:Selecting last orders for each user using Npgsql and EF Core 3.1使用 Npgsql 和 EF Core 3.1 为每个用户选择最后的订单
【发布时间】:2020-07-24 14:53:04
【问题描述】:

我有一个 Order 实体,它有两个名为 UserIdCreationTimeUtc 的主列。我要做的是为每个用户选择最后一个Order(当然基于UserId 列)。通常我希望通过分组和排序来做到这一点。这是我尝试过的:

var q = _context.Orders.AsNoTracking()
    .Where(t => t.CreationTimeUtc > SomeDate)
    .GroupBy(t => t.UserId)
    .Select(g => g.OrderBy(t => t.CreationTimeUtc).First())
    .Skip(10)
    .Take(10)
    .ToList();

但是运行查询会出现这个错误:

System.InvalidOperationException:LINQ 表达式 '(GroupByShaperExpression: KeySelector: (r.UserId), 元素选择器:(实体形状表达式: 实体类型:订单 值缓冲区表达式: (ProjectionBindingExpression:EmptyProjectionMember) IsNullable: False)

我搜索了很多,似乎 EF Core 不支持分组!这是真的?如果是这样,我该如何解决这个问题?我需要加载内存中的所有行还是有任何基于 LINQ 的方法?你有什么想法吗?提前致谢。

我正在使用EF Core 3.1ASP.NET Core 3.1Npgsql 3.1PostgreSQL 12C# 8

【问题讨论】:

  • 你会考虑使用原始 sql 方法吗?
  • @CaiusJard 我不喜欢使用行 SQL

标签: c# postgresql .net-core entity-framework-core npgsql


【解决方案1】:

您可以通过以下方式做到这一点:

var result = ctx.Users
    .Select(u => u.Orders
        .Where(t => t.CreationTimeUtc > someDate)
        .OrderBy(t => t.CreationTimeUtc)
        .First())
    .ToList();

表达几乎相同的东西的方式略有不同。我会跟进相关人员,了解如何翻译您的特定模式。

【讨论】:

  • “您的特定模式”是 EF6 查询翻译器支持的常见模式(无需客户端评估!)。还记得Query with GroupBy or GroupJoin throws exception #17068 讨论的一部分吗?它以Translate GroupBy followed by FirstOrDefault over group #12088 和更通用的Support ability to select top N of each group #13805 结尾——两者都是Backlog 中的“增强”,即——嗯,你知道,总有一天……
  • 我并不是说它不应该被翻译——但我​​们肯定会优先考虑没有解决方法的模式;在这种情况下,您至少可以通过另一个 LINQ 构造生成正确的 SQL 和结果。翻译所有可能的 LINQ 结构是一项无限的任务,我们一直在努力。
  • 在这种情况下我无法访问用户。 Orders 中只有 UserId 字段。
  • 但是你可以加载用户,对吧? Order 是否有用户导航属性?您的问题在哪里说明您的订单有用户或需要它?我看到您想要问题中每个用户 ID 的最新订单 - 您是否要求提供您不想要的东西?
  • @CaiusJard 订单没有用户导航属性。实际上,用户正在使用外部服务,而我无权访问它。只有用户 ID。
猜你喜欢
  • 2023-03-21
  • 2011-05-02
  • 2021-09-05
  • 1970-01-01
  • 2021-12-26
  • 2010-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多