'LINQ Expression GroupBy Select First
I've got a question on LINQ Expression. I need to replicate the following lambda:
var result = processRevisions
OrderByDescending(pr => pr.CreatedAt)
GroupBy(pr => pr.IdProcess)
Select(pr => pr.First());
which result is the latest revision created for every process, in LINQ expression.
I start with this code:
Expression<Func<ProcessRevision, DateTime>> orderProcessRevision = f => f.CreatedAt;
Expression<Func<ProcessRevision, long>> groupProcessRevision = f => f.IdProcess;
Expression<Func<ProcessRevision, ProcessRevision>> selectProcessRevision = f => f;
processRevisions = await processRevisionRepository.GetDatasByLastRevisionAsync(orderProcessRevision, groupProcessRevision, selectProcessRevision);
The repository is as follows:
public async Task<IEnumerable<T>> GetDatasByLastRevisionAsync(
Expression<Func<T, DateTime>> order,
Expression<Func<T, long>> group,
Expression<Func<T, T>> select)
{
IQueryable<T> query = dbContext.Set<T>();
query = query.OrderByDescending(order);
query = query.GroupBy(group);
query = query.Select(select);
return await query.ToListAsync();
}
The only part of the query which works is the orderbydescending
. Then, the groupby
yields an error (implicit convert IGrouping
to IQueryable
) and also the select first item of each group goes in error.
How to apply the groupby
(igrouping
) to IQueryable
and for every group take the first object?
Thanks for help.
Solution 1:[1]
I think the issue is that GroupBy doesn't return an IQueryable<T>
but an IEnumerable<TResult>
where TResult is of type IGrouping<TKey, TElement>
.
Expression<Func<ProcessRevision, DateTime>> orderProcessRevision = f => f.CreatedAt;
Expression<Func<ProcessRevision, long>> groupProcessRevision = f => f.IdProcess;
// Fix the type and update the lambda to select the first item in the group
Expression<Func<IGrouping<long, ProcessRevision>, ProcessRevision>> selectProcessRevision = f => f.First();
processRevisions = await processRevisionRepository.GetDatasByLastRevisionAsync(orderProcessRevision, groupProcessRevision, selectProcessRevision);
public async Task<IEnumerable<T>> GetDatasByLastRevisionAsync(
Expression<Func<T, DateTime>> order,
Expression<Func<T, long>> group,
Expression<Func<IGrouping<long, T>, T>> select)
{
IQueryable<T> query = dbContext.Set<T>();
query = query.OrderByDescending(order);
// Don't reassign, create a new var
var grouped = query.GroupBy(group);
var selected = grouped.Select(select);
return await selected.ToListAsync();
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Emaro |