0

I am new to using generics. Very powerful stuff but a bit confusing to me and I'm trying to understand how to use the following code:

    public async Task<IEnumerable<TEntity>> Find(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
    {
        try
        {
            return await this.GetQuery(predicate, orderExpression);
        }
        catch (Exception e)
        {
            return null;
        }
    }

    public async Task<IQueryable<TEntity>> GetQuery(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
    {
        IQueryable<TEntity> qry = this.DBSet;

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

        if (orderExpression != null)
            return orderExpression(qry);


        return qry;
    }

I am able to call the find method with a predicate like so:

@code {
    [Parameter]
    public string CurrentID { get; set; }
    Repository2<User> repository2 = new Repository2<User>();
    IEnumerable<User> users;
    User user = new User();

    protected override async Task OnInitializedAsync()
    {
        users = await Task.Run(() => repository2.Find(u => u.ID == Convert.ToInt32(CurrentID)));
        user = users.SingleOrDefault();
    }

    protected void UpdateUser()
    {
        repository2.Update<User>(user);
        repository2.SaveChanges();
        navidationMananger.NavigateTo("Users");
    }

    void Cancel()
    {
        navidationMananger.NavigateTo("Users");
    }

}
   

However I am unable to figure out how use the OrderBy functionality of the above Find method.

How would I call this method passing an order by as the second parameter? If you could explain it a bit so I understand why it works that would be most appreciated.

Jim
  • 11
  • 2

2 Answers2

1

Its LINQ syntax, so you can call OrderBy on the output of the Find since it returns either an IEnumerable or IQueryable. Below is one example. Or you could return it as an object, then call OrderBy or OrderByDescending later on. Its usually best to do them together though, because of Lazy Loading, which defers execution on those operations until it actually needs to be manifested, either looped through or returned as a concrete type, like a List, as opposed to an IEnumerable. Make sense?

@code {
    [Parameter]
    public string CurrentID { get; set; }
    Repository2<User> repository2 = new Repository2<User>();
    IEnumerable<User> users;
    User user = new User();

    protected override async Task OnInitializedAsync()
    {
        users = await Task.Run(() => repository2
            .FindAll(u => u.ID == Convert.ToInt32(CurrentID)).OrderBy(v => v.ID));
        user = users.SingleOrDefault();
    }

    protected void UpdateUser()
    {
        repository2.Update<User>(user);
        repository2.SaveChanges();
        navidationMananger.NavigateTo("Users");
    }

    void Cancel()
    {
        navidationMananger.NavigateTo("Users");
    }

}

Or you could simplify the call to this:

        user = await Task.Run(() => repository2
            .FindAll(u => u.ID == Convert.ToInt32(CurrentID))
            .OrderBy(v => v.ID).FirstOrDefault());
Dan Csharpster
  • 2,662
  • 1
  • 26
  • 50
  • Yes, perfectly, thank you for the example and explanation. – Jim Jan 12 '21 at 20:40
  • Happy to help! FYI, if you hit the check to mark this as the accepted answer, it can help others who search for this and also take this question off of the unanswered question list, so others don't keep coming here to try and answer it as well. – Dan Csharpster Jan 12 '21 at 20:46
  • Good explanation but it didn't work. I can use .Result.OrderBy but that defeats the purpose of doing it at the same time since it's done after the Task completes. When I try to use the above I get an error that OrderBy is not defined. – Jim Jan 12 '21 at 21:57
  • I didn't double check this. Find returns a single item, so there's no list to sort and OrderBy doesn't work on single items. I'll update the example with FindAll. – Dan Csharpster Jan 12 '21 at 22:09
  • await repository2.Find(s => s.StationID == 1, q => q.OrderBy(s => s.DisplayOrder)); is the correct call syntax. Verified it is working. More info here on it: https://stackoverflow.com/questions/16009694/dynamic-funciqueryabletentity-iorderedqueryabletentity-expression – Jim Jan 13 '21 at 15:23
1

I found the answer in another thread:

Dynamic Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> Expression

await repository2.Find(s => s.StationID == 1, q => q.OrderBy(s => s.DisplayOrder));
Benzara Tahar
  • 2,058
  • 1
  • 17
  • 21
Jim
  • 11
  • 2