在 .NET Core 中使用 GroupBy

Posted

技术标签:

【中文标题】在 .NET Core 中使用 GroupBy【英文标题】:Using GroupBy in .NET Core 【发布时间】:2021-03-12 13:22:39 【问题描述】:

我需要对我的查询结果进行分组。主要问题是当我使用 GroupBy 时,GroupBy 语句的返回类型是 IGrouping,这与我的方法的返回类型 List<MyViewModel> 不同。所以这两种类型不匹配。现在第一个选项是更改我的方法的返回类型。在这种情况下,如何在视图层(Razor 页面的 html 部分)中访问 ViewModel 的属性?

在不改变我的方法返回类型的情况下使用 GroupBy 有什么选择吗?

            public List<MultimediaViewModel> Search(MultimediaSearchModel searchModel)
    
        
        var query = _hContext.Multimedias.Include(x => x.Ceremony)
            .Select(g => new MultimediaViewModel
        
            Id = g.Id,
            Title = g.Title,
            CeremonyId = g.CeremonyId,
            Ceremony = g.Ceremony.Title,
            FileAddress = g.FileAddress,
        ).AsEnumerable().GroupBy(g => g.CeremonyId).ToList();

        if (!string.IsNullOrWhiteSpace(searchModel.Title))
            query = query.Where(g => g.Title.Contains(searchModel.Title)).ToList();

        if (searchModel.CeremonyId != 0)
            query = query.Where(g => g.Key == searchModel.CeremonyId).ToList();

        return query;
    

由于方法返回类型和Group by返回类型之间的差异,上面的代码不起作用。

【问题讨论】:

无法自动执行此操作。在 GroupBy 之后,您只有 IGrouping 结果,稍后应重新映射。按 CeremonyId 分组有什么意义?在MultimediaViewModel中应该有适当的理由 对于每个不同的仪式 ID,可能有多个多媒体。你要哪一个? 对于每个仪式 ID,可能有多个多媒体。所以当我们要保存每一个多媒体项时,我们应该通过 CeremonyId 将它分配给仪式,CeremonyId 是多媒体模型中 Ceremony 模型的外键。 GroupBy 有几个重载,其中一个返回 IEnumerable&lt;TResult&gt;。使用提供所需返回类型的重载之一。 @Amin,最好用MultimediaViewModel 定义更新问题。 【参考方案1】:

在不完全了解您的业务需求的情况下,我可以提供 2 种方法来解决此问题

    在方法外使用GroupBy,使用Search方法返回一个列表,然后使用GroupBy对其进行分组

    如果你只需要返回一个特定CeremonyId的MultimediaViewModel列表,你可以搜索IGrouping的列表得到一个特定的子列表

     public List<MultimediaViewModel> Search(MultimediaSearchModel searchModel)
        
            var query = _hContext.Multimedias.Include(x => x.Ceremony).Select(g => new MultimediaViewModel
            
                Id = g.Id,
                Title = g.Title,
                CeremonyId = g.CeremonyId,
                Ceremony = g.Ceremony.Title,
                FileAddress = g.FileAddress
            ).GroupBy(g => g.CeremonyId).ToList();  
    
     return query.FirstOrDefault(g=>g.Key==searchModel.CeremonyId).ToList();
     //you can just use Where to find all  of the MultimediaViewModel instead of using GroupBy 
    

编辑 可能将结果作为字典返回

public Dictionary<string, List<MultimediaViewModel>> Search(MultimediaSearchModel searchModel)

    var query = _hContext.Multimedias.Include(x => x.Ceremony).Select(g => new MultimediaViewModel
    
        Id = g.Id,
        Title = g.Title,
        CeremonyId = g.CeremonyId,
        Ceremony = g.Ceremony.Title,
        FileAddress = g.FileAddress
    ).GroupBy(g => g.CeremonyId).ToList();
    return query.ToDictionary(k => k.Key, v => v.ToList());


  

【讨论】:

感谢迈克尔的回复。但让我解释一下我的问题。如果我的 searchModel 参数为空,我需要列出所有仪式。所以当页面加载时,我们应该有一个多媒体仪式专辑列表。我们已经有了这个列表,但每个多媒体项目都会重复仪式。我想更改此 saerch 方法以根据其仪式向我返回多媒体项目。例如假设我们有 3 个仪式。对于每个仪式,我们有 4 个多媒体项目。现在列表向我们显示了 12 行,而预计有 3 行。 请您建议如何使用 Group By 外部方法? 根据您的回答,我认为您需要将 CeremonyId 的字典返回到 MultimediaViewModel 的列表中,我已经用一种方法编辑了我的答案 我已根据您的评论编辑了我的方法,但收到以下错误:错误 CS0029 无法隐式转换类型 'System.Collections.Generic.Dictionary>' 到 'System.Collections.Generic.Dictionary>' xxx.Infrastructure.EFCore 我已将类型字符串更改为长,问题已解决,但我不知道如何在我的剃须刀页面的 HTML 部分访问以下项目及其值? Id,Title,CeremonyId,Ceremony,FileAddress

以上是关于在 .NET Core 中使用 GroupBy的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用AutoMapper进行实体映射

如何使用 EF Core 在 ASP.NET Core 中取消应用迁移

在.NET Core中使用MEF

asp.net core中托管SPA应用

Net Core 多项目开发(net core 类库项目使用)

.Net Core 身份在 .Net Core 5.0 中添加公司名称作为用户登录过程的一部分