c# - 动态 LINQ GroupBy 多列

标签 c# .net linq entity-framework dynamic-linq

我需要将以下 LINQ 查询转换为接受基于用户输入的多个分组列的动态 LINQ。基本上我有一堆应用分组的下拉列表,我不想枚举分组的每个组合。如果 Dynamic LINQ 失败,我可能不得不手动构造一个 SQL 查询,但没有人愿意这样做。

var grouping = ( from entry in ObjectContext.OmniturePageModules
    where entry.StartOfWeek >= startDate && entry.StartOfWeek <= endDate &&
        ( section == "Total" || section == "All" || entry.Section == section ) &&
        ( page == "Total" || page == "All" || entry.Page == page ) &&
        ( module == "Total" || module == "All" || entry.Module == module ) 
    group entry by new
    {
        entry.Page, // I want to be able to tell this anonymous type
        entry.Module, // which columns to group by
        entry.StartOfWeek // at runtime
    }
    into entryGroup
    select new
    {
        SeriesName = section + ":" + entryGroup.Key.Page + ":" + entryGroup.Key.Module,
        Week = entryGroup.Key.StartOfWeek,
        Clicks = entryGroup.Sum( p => p.Clicks )
    } );

我不知道如何执行此操作,因为 Dynamic LINQ 在“hello world!”之外完全没有记录。 select/where/orderby 案例。我只是想不通语法。

类似于:(?)

var grouping = ObjectContext.OmniturePageModules.Where(entry => entry.StartOfWeek >= startDate && entry.StartOfWeek <= endDate &&
                                           ( section == "Total" || section == "All" || entry.Section == section ) &&
                                           ( page == "Total" || page == "All" || entry.Page == page ) &&
                                           ( module == "Total" || module == "All" || entry.Module == module ))
                                           .GroupBy("new (StartOfWeek,Page,Module)", "it")
                                           .Select("new (Sum(Clicks) as Clicks, SeriesName = section + key.Page + Key.Module, Week = it.Key.StartOfWeek)");

我在 System.Linq.Dynamic 中使用 DynamicQueryable 类。请参阅:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

跟进: Enigmativity 的解决方案大部分 都有效。出于某种原因,它不想按日期时间“StartOfWeek”列进行分组——解决方法只是进行二次分组:

var entries = ( from entry in ObjectContext.OmniturePageModules
                            where entry.StartOfWeek >= startDate
                                && entry.StartOfWeek <= endDate
                                && ( section == "Total" || section == "All" || entry.Section == section )
                                && ( page == "Total" || page == "All" || entry.Page == page )
                                && ( module == "Total" || module == "All" || entry.Module == module )
                            select entry ).ToArray(); // Force query execution

            var grouping = from entry in entries
                            let grouper = new EntryGrouper( entry, section, page, module )
                            group entry by grouper into entryGroup
                            select new
                            {
                                entryGroup.Key.SeriesName,
                                entryGroup.Key.Date, 
                                Clicks = entryGroup.Sum( p => p.Clicks ),
                            };

            var grouping2 = (from groups in grouping
                            group groups by new {groups.SeriesName, groups.Date } into entryGroup
                            select new
                            {
                               entryGroup.Key.SeriesName,
                               entryGroup.Key.Date,
                               Clicks = entryGroup.Sum( p => p.Clicks ),
                            } );

但这似乎会严重降低性能... =/

最佳答案

这是在 Dynamic LINQ 中——当然您在运行时构建 GroupBy 和 Select 字符串:

var double_grouping = ( ObjectContext.OmniturePageModules.Where( entry => entry.StartOfWeek >= startDate
                     && entry.StartOfWeek <= endDate
                     && ( section == "Total" || section == "All" || entry.Section == section )
                     && ( page == "Total" || page == "All" || entry.Page == page )
                     && ( module == "Total" || module == "All" || entry.Module == module ) )
                     .GroupBy( "new ( it.Section, it.Page, it.StartOfWeek )", "it" ) )
                     .Select( "new ( Sum(Clicks) as Clicks, Key.Section as SeriesSection, Key.Page as SeriesPage, Key.StartOfWeek as Week )" );

下面是正常的 LINQ 方法,我在一位同事指出之前一直没有想到它——这基本上是 Enigmativity 没有石斑鱼类的解决方案:

var grouping = ( from entry in ObjectContext.OmniturePageModules
    where entry.StartOfWeek >= startDate && entry.StartOfWeek <= endDate &&
        ( section == "Total" || section == "All" || entry.Section == section ) &&
        ( page == "Total" || page == "All" || entry.Page == page ) &&
        ( module == "Total" || module == "All" || entry.Module == module )
    group entry by new
    {
        Section = section == "All" ? entry.Section : section,
        Page = page == "All" ? entry.Page : page,
        Module = module == "All" ? entry.Module : module,
        entry.StartOfWeek
    }
        into entryGroup
        select new
        {
            SeriesName =
            entryGroup.Key.Section + ":" + entryGroup.Key.Page + ":" + entryGroup.Key.Module,
            Week = entryGroup.Key.StartOfWeek,
            Clicks = entryGroup.Sum( p => p.Clicks )
        } );

关于c# - 动态 LINQ GroupBy 多列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3929041/

相关文章:

c# - 在 Windows Docker 容器中设置语言和区域设置

c# - 从 .NET 应用程序使用 OTRS TicketConnector

c# - 如何将位图返回给浏览器 WebApi

c# - System.Net.Sockets.Socket() 如何使用它的参数?

c# - 如何解析人为输入的逻辑属性,例如这个和(那个或另一个)?

c# - 如何逐一生成IEnumerable的元素

c# - LinQ WHERE string.Contains 或 string.IndexOf?

c# - 我可以使用 DataGridViewComboBoxColumn 来显示类对象列表吗?

c# - 我可以使用 XmlSerializer 控制某些字段的序列化吗

c# - 为什么 linq to object 手动实现迭代器?