Search code examples
c#linqgroup-bylinq-expressions

Adding a dynamic GroupBy expression to an IQueryable


I want to pass a dynamic GroupBy expression into an IQueryable. I'm already doing something similar with a Where clause that is working OK.

The purpose of the group by is then to allow my to extract just the most recent version of each record in each respective group. For example:

object MyMethod(Expression<Func<MyObj,int>> whereExpr = null, 
              Expression<Func<MyObj,int>> groupByExpr = null)
{
    var query = DbSet.Where(x => x.IsArchived == false);


    if (whereExpr != null) {
        query = query.Where(whereExpr); // this is working
    }

    if (groupByExpr != null) {
        query = query.GroupBy(groupByExpr).Select(g => g.OrderByDescending(x => x.CreatedDate).FirstOrDefault()).AsQueryable(); // this is throwing a client side error
    }
    
    return new GridDevExtremeDataSource<TEntity>(query);
}

Then called with something like

var obj = MyMethod(whereExpr: x => x.Id > 100, groupByExpr: x => x.CategoryId)

This is throwing a client side error:

Error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidOperationException: Nullable object must have a value.


Solution

  • Actually you are trying to get latest item from the group. Looks like EF Core, at least up to version 7, has limitation in such queries.

    I have prepared another answer for similar problem and implemented custom DistinctBy extension implementation which mimic what EF Core should do for retrieving last record of grouped items.

    So, you problematic line with this function should looks like:

    query = query.DistinctBy(groupByExpr, x => x.CreatedDate);