Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select -> Group -> Order -> Select In one repository function

I know the title is not good.

I have a service that contain all of my entity functions.

In my service there is a function with this structure

IList<T> GetAllPaged<TKey>(
    List<Expression<Func<T, bool>>> predicate, 
    Expression<Func<T, TKey>> orderKeySelector
);

This function gets data from one entity and orders it.

Now I want to do more.

First to select from one entity then group it in order it and at the end select new items from grouped items.

Something like this:

IList<TReturn> GetAllPaged<TResult, TKey, TGroup, TReturn>(
    List<Expression<Func<T, bool>>> predicate, 
    Expression<Func<T, TResult>> firstSelector, 
    Expression<Func<TResult, TKey>> orderSelector, 
    Func<TResult, TGroup> groupSelector, 
    Func<IGrouping<TGroup, TResult>, TReturn> selector
);

Is that possible?


1 Answers

Here is a solution to what I think you asked for.

First, the base repository. I've created a base repository because I hope you will not expose this madness to the application but to the repositories only.

abstract class BaseRepo<TEntity>
{
    // If you're using Entity Framework, this method could 
    // be implemented here instead.
    protected abstract IQueryable<TEntity> Entities { get; }

    protected IList<TReturn> GetAllPaged<TResult, TKey, TGroup, TReturn>(
        List<Expression<Func<TEntity, bool>>> predicates,
        Expression<Func<TEntity, TResult>> firstSelector,
        Expression<Func<TResult, TKey>> orderSelector,
        Func<TResult, TGroup> groupSelector,
        Func<IGrouping<TGroup, TResult>, TReturn> selector)
    {
        return predicates
            .Aggregate(Entities, (current, predicate) => current.Where(predicate))
            .Select(firstSelector)
            .OrderBy(orderSelector)
            .GroupBy(groupSelector)
            .Select(selector)
            .ToList();
    }
}

Then the implementation.

class HorseRepo : BaseRepo<Horse>
{
    // This will of course be some data source
    protected override IQueryable<Horse> Entities
    {
        get
        {
            return new List<Horse> {
                new Horse { Id = 1, Name = "Mr Horse", Color = "Brown" },
                new Horse { Id = 2, Name = "Mrs Horse", Color = "White" },
                new Horse { Id = 3, Name = "Jr Horse", Color = "White" },
                new Horse { Id = 4, Name = "Sr Horse", Color = "Black" },
                new Horse { Id = 5, Name = "Dr Horse", Color = "Brown" },
            }.AsQueryable();
        }
    }

    // This is what I think you should expose to the application
    // This is the usage of the expression fest above.
    public IEnumerable<GroupedHorses> GetGroupedByColor() {
        return horseRepo.GetAllPaged(
            new List<Expression<Func<Horse, bool>>> {
                h => h.Name != string.Empty, 
                h => h.Id > 0
            },
            h => new HorseShape { Id = h.Id, Name = h.Name, Color = h.Color },
            hs => hs.Name,
            hs => hs.Color,
            g => new GroupedHorses
            {
                Color = g.Key,
                Horses = g.ToList()
            }
        );
    }
}

Some classes needed:

class GroupedHorses
{
    public string Color { get; set; }
    public IList<HorseShape> Horses { get; set; }
}

class HorseShape
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Color { get; set; }
}

// Define other methods and classes here
class Horse
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Color { get; set; }
    public string UninterestingProperty { get; set; }
}
like image 166
Mikael Östberg Avatar answered Nov 21 '25 09:11

Mikael Östberg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!