title: Dynamic LINQ GroupBy Multiple Columns
body: <p>I need to translate the following LINQ query to Dynamic LINQ that accepts several grouping columns based on user input. Basically I have a bunch of dropdownlists that apply groupings and I don't want to enumerate every combination of groupings. If Dynamic LINQ fails, I may have to construct a SQL query manually, and nobody wants that. </p>
  
  <pre><code>var grouping = ( from entry in ObjectContext.OmniturePageModules
      where entry.StartOfWeek &gt;= startDate &amp;&amp; entry.StartOfWeek &lt;= endDate &amp;&amp;
          ( section == "Total" || section == "All" || entry.Section == section ) &amp;&amp;
          ( page == "Total" || page == "All" || entry.Page == page ) &amp;&amp;
          ( 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 =&gt; p.Clicks )
      } );
  </code></pre>
  
  <p>I have no clue how to do this as Dynamic LINQ is totally undocumented outside of the "hello world!" select/where/orderby cases. I just can't figure out the syntax. </p>
  
  <p>Something like:(?)</p>
  
  <pre><code>var grouping = ObjectContext.OmniturePageModules.Where(entry =&gt; entry.StartOfWeek &gt;= startDate &amp;&amp; entry.StartOfWeek &lt;= endDate &amp;&amp;
                                             ( section == "Total" || section == "All" || entry.Section == section ) &amp;&amp;
                                             ( page == "Total" || page == "All" || entry.Page == page ) &amp;&amp;
                                             ( 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)");
  </code></pre>
  
  <p>I'm using the DynamicQueryable class in System.Linq.Dynamic. See: <a href="http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx" rel="noreferrer">http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx</a></p>
  
  <p>Follow-up: 
  Enigmativity's solution worked <em>mostly</em>. For some reason it doesn't want to group by the datetime "StartOfWeek" column -- workaround is just to do a secondary grouping:</p>
  
  <pre><code>var entries = ( from entry in ObjectContext.OmniturePageModules
                              where entry.StartOfWeek &gt;= startDate
                                  &amp;&amp; entry.StartOfWeek &lt;= endDate
                                  &amp;&amp; ( section == "Total" || section == "All" || entry.Section == section )
                                  &amp;&amp; ( page == "Total" || page == "All" || entry.Page == page )
                                  &amp;&amp; ( 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 =&gt; 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 =&gt; p.Clicks ),
                              } );
  </code></pre>
  
  <p>but this seems to seriously degrade performance... =/</p>