【问题标题】:Take each first element of the group by取组的每个第一个元素
【发布时间】:2021-05-26 11:46:34
【问题描述】:

如何使用 EF 5 获取组中的每个第一个元素?

      var result = await context.SomeDbSet
          .Where(...)
          .GroupBy(x => new { x.SomeField, ... })
          .Select(x => x.First())
          .ToListAsync();

我得到了不受支持的异常。

如何正确重写查询?谢谢。

【问题讨论】:

  • 其实纯EF没有办法做到这一点,除了扭动SQL。无论如何,如果你没问题,我可以通过第三方扩展提出解决方案。
  • @SvyatoslavDanyliv 感谢您的回答。这就是我需要知道的全部 - 只是没有 sql 的 linq 是不够的。无论如何,有人看到你的例子可能会很好。

标签: entity-framework entity-framework-core linq-to-entities entity-framework-core-5


【解决方案1】:

你不能通过分组来做到这一点。 SQL 有一个限制 - 使用 GROUP BY 您只能选择分组键和聚合结果。此限制肯定扩展到LINQ to Entities - 在GroupBy 之后,您只能选择分组键和聚合结果。

这样的结果可以通过SQL和Window函数来实现:

SELECT
  r.*,
FROM 
(
   SELECT 
      s.*, 
      ROW_NUMBER() OVER(PARTITION BY s.SomeField1, s.SomeField2 ORDER BY s.SomeDate) AS RN
   FROM SomeDbSet s
   WHERE ...
) r
WHERE r.RN = 1

对于那些想留在LINQ的人,我建议扩展(免责声明:我是扩展创建者)linq2db.EntityFrameworkCore

您可以通过 LINQ 在上面编写查询

var rnQuery = 
   from s in context.SomeDbSet
   where ...
   select new 
   {
      Data = s,
      RN = Sql.Ext.RowNumber().Over()
              .PartitionBy(s.SomeField1, s.SomeField2)
              .OrderBy(s.SomeDate)
              .ToValue()
   }

var resultQuery = await rnQuery
   .Where(r => r.RN == 1)
   .Select(r => r.Data)
   .ToLinqToDB();

var result = resultQuery.ToList();

// async variant may need ToListAsyncLinqToDB() call 
// because of collision in async extension methods between EF Core and linq2db
var result = await resultQuery.ToListAsyncLinqToDB();

【讨论】:

    猜你喜欢
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    相关资源
    最近更新 更多