Skip to main content
 首页 » 编程设计

c#之LINQ:分组后从实体集合中选择最小值和最大值

2024年02月25日37hnrainll

目标是从实体(外键)的集合中获取第一个 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) 

请您参考如下方法:

这是诀窍。

要通过使用集合导航属性进行内部连接,只需使用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]