【问题标题】:LINQ: Select the Min and Max values from a collection on an entity after groupingLINQ:分组后从实体的集合中选择最小值和最大值
【发布时间】:2018-08-10 15:47:57
【问题描述】:

目标是从实体(外键)的集合中获取第一个 DateTime 和 Last DateTime。我的实体是一个组织,我的收藏是发票。我正在对结果进行分组,因为不幸的是组织不是唯一的。我正在处理重复数据,不能假设我的组织是唯一的,因此我按我的实体上的数字字段进行分组。

我正在使用 .NET Core 2.1.2 和 Entity Framework。

我正在尝试从 LINQ 生成以下查询:

SELECT MIN([organization].[Id]) AS Id, MIN([organization].[Name]) AS Name, 
MIN([organization].[Number]) AS Number, MIN([invoice].[Date]) 
AS First, MAX([invoice].[Date]) AS Last
FROM [organization]
INNER JOIN [invoice] ON [invoice].[OrganizationId] = [organization].[Id]
GROUP BY [organization].[Number], [organization].[Name]
ORDER BY [organization].[Name]

但是我不知道如何编写 LINQ 查询以使其生成此结果。

我知道了:

await _context
            .Organization
            .Where(z => z.Invoices.Any())
            .GroupBy(organization => new
            {
                organization.Number,
                organization.Name
            })
            .Select(grouping => new
            {
                Id = grouping.Min(organization => organization.Id),
                Name = grouping.Min(organization => organization.Name),
                Number= grouping.Min(organization => organization.Number),
                //First = ?,
                //Last = ?
            })
            .OrderBy(z => z.Name)
            .ToListAsync();

我不知道如何以生成上述内容的方式编写 LINQ 查询。

我还有几个问题:

  • 对于 Id、Name 和 Number 的 Min 语句是否正确获取 分组中的第一个元素?
  • 我需要加入语句还是“WHERE EXISTS”更好(这是在我更改代码之前生成的)?

有人知道如何完成 LINQ 语句的编写吗?因为我必须从我的组织实体的发票集合中获取第一个和最后一个日期:

organization.Invoices.Min(invoice => invoice.Date)
organization.Invoices.Max(invoice => invoice.Date)

【问题讨论】:

  • 在 EF Core 中搜索加入
  • 请参阅下面的回复。这就是我一直在寻找的东西。我还不知道 LINQ 如何很好地转换为 SQL。 Ivan Stoev 在下面的回答会生成一个内部连接并执行我需要它执行的操作。

标签: c# linq .net-core entity-framework-core


【解决方案1】:

这是诀窍。

要通过使用集合导航属性使inner join 变得简单,请使用SelectMany 并投影您以后需要的所有原语 属性(这对于当前的EF Core 查询翻译器很重要)。然后执行GroupBy 并投影关键属性/聚合。最后下单。

所以

var query = _context
    .Organization
    .SelectMany(organization => organization.Invoices, (organization, invoice) => new
    {
        organization.Id,
        organization.Number,
        organization.Name,
        invoice.Date
    })
    .GroupBy(e => new
    {
        e.Number,
        e.Name
    })
    .Select(g => new
    {
        Id = g.Min(e => e.Id),
        Name = g.Key.Name,
        Number = g.Key.Number,
        First = g.Min(e => e.Date),
        Last = g.Max(e => e.Date),
    })
    .OrderBy(e => e.Name);

被翻译成

SELECT MIN([organization].[Id]) AS [Id], [organization].[Name], [organization].[Number], 
    MIN([organization.Invoice].[Date]) AS [First], MAX([organization.Invoice].[Date]) AS [Last]
FROM [Organization] AS [organization]
INNER JOIN [Invoice] AS [organization.Invoice] ON [organization].[Id] = [organization.Invoice].[OrganizationId]
GROUP BY [organization].[Number], [organization].[Name]
ORDER BY [organization].[Name]

【讨论】:

  • 我不知道它会处理这样的 selectmany 和 select,它仍然会生成 SQL 语句并且不在内存中进行评估。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 2015-10-15
  • 1970-01-01
相关资源
最近更新 更多