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