Home > Back-end >  Can Not Convert From Expression<Func<T, decimal>> To Func<T, decimal> In Sum Metho
Can Not Convert From Expression<Func<T, decimal>> To Func<T, decimal> In Sum Metho

Time:04-10

In the following code when I want to get sum for sumField I'm getting an error(Can Not Convert From Expression<Func<T, decimal>> To Func<T, decimal>)

If I remove the Expression from the groupBy and sumField parameters, my problem will be solved, but in this case, all the data will be sent to the application as IEnumrable and then group by

How can I do this operation Iqueryable??

public virtual async Task<Dictionary<TKey, decimal>> SumAsync<TKey>(
    Expression<Func<T, TKey>> groupBy,
    Expression<Func<T, decimal>> sumField,
    Expression<Func<T, bool>> predicate = null,
    List<Expression<Func<T, object>>> includes = null,
    string includeString = null)
{
    IQueryable<T> query = DbSet;

    if (includes != null) query = includes.Aggregate(query, (current, include) => current.Include(include));

    if (!string.IsNullOrWhiteSpace(includeString))
    {
        var incluseSplit = includeString.Split(',');
        query = incluseSplit.Aggregate(query, (current, include) => current.Include(include));
    }

    if (predicate != null) query = query.Where(predicate);

    var group = query.GroupBy(groupBy)
                    .Select(g =>
                                new
                                {
                                    Key = g.Key,
                                    SumValue = g.Sum(sumField)
                                }
                            )
                    .AsQueryable();


    return group.ToDictionary(s => s.Key, s => s.SumValue);
}

CodePudding user response:

Can you not use a different overload of .GroupBy() as follows:

...

var group = query.GroupBy(groupBy, sumField) // sumField is used to select the elements returned in the grouping
    .Select(g =>
        new
        {
            Key = g.Key,
            SumValue = g.Sum() // Now only .Sum() is required
        }
    ); // and no .AsQueryable() necessary

...

I would also note that your method is marked async, but does not await anything, so will run synchronously. You might want to use .ToDictionaryAsync() at the end instead.

CodePudding user response:

It is difficult, but possible, to do that without LINQKit. So first variant is with LINQKit, other need dynamic Expression Tree composing.

Activate LINKQKit via DbContextOptions:

builder
    .UseSqlServer(connectionString)
    .WithExpressionExpanding(); // enabling LINQKit extension

Then we can use LINQKit extension Invoke

public virtual Task<Dictionary<TKey, decimal>> SumAsync<TKey>
(
    Expression<Func<T, TKey>> groupBy,
    Expression<Func<T, decimal>> sumField,
    Expression<Func<T, bool>> predicate = null
)
{
    IQueryable<T> query = DbSet;

    if (predicate != null) 
        query = query.Where(predicate);

    var group = query
        .GroupBy(groupBy)
        .Select(g =>
            new
            {
                Key = g.Key,
                SumValue = g.Sum(e => sumField.Invoke(e))
            }
         );

    return group.ToDictionaryAsync(s => s.Key, s => s.SumValue);
}

Also removed Includes staff, it is completely ignored by EFCore when you use GroupBy or Select

  • Related