Home > Enterprise >  How orderBy dynamically, based on navigation property
How orderBy dynamically, based on navigation property

Time:09-17

var query = TableNoTracking;
query = query
            .Include(r => r.UserRoles).ThenInclude(o => o.Role)
            .Include(c => c.Photos.Where(x => x.IsMain))
            .Include(w => w.Wallets);

my sort part is like below and I want handle sorting dynamically

   if (!string.IsNullOrWhiteSpace(filterUser.SortBy))
            {
                switch (filterUser.Reverse)
                {
                    //reverse
                    case true:
                        switch (filterUser.SortBy)
                        {
                            case UserNavigationPropsForSort.InventorySum:
                                query = query.OrderByDescending(x => x.Wallets.Select(y => y.Inventory).Sum());
                                break;
                            case UserNavigationPropsForSort.InterMoneySum:
                                query = query.OrderByDescending(x => x.Wallets.Select(y => y.InterMoney).Sum());
                                break;
                            case UserNavigationPropsForSort.ExitMoneySum:
                                query = query.OrderByDescending(x => x.Wallets.Select(y => y.ExitMoney).Sum());
                                break;
                            case UserNavigationPropsForSort.OnExitMoneySum:
                                query = query.OrderByDescending(x => x.Wallets.Select(y => y.OnExitMoney).Sum());
                                break;
                        }

                        break;
                    case false:
                        switch (filterUser.SortBy)
                        {
                            case UserNavigationPropsForSort.InventorySum:
                                query = query.OrderBy(x => x.Wallets.Select(y => y.Inventory).Sum());
                                break;
                            case UserNavigationPropsForSort.InterMoneySum:
                                query = query.OrderBy(x => x.Wallets.Select(y => y.InterMoney).Sum());
                                break;
                            case UserNavigationPropsForSort.ExitMoneySum:
                                query = query.OrderBy(x => x.Wallets.Select(y => y.ExitMoney).Sum());
                                break;
                            case UserNavigationPropsForSort.OnExitMoneySum:
                                query = query.OrderBy(x => x.Wallets.Select(y => y.OnExitMoney).Sum());
                                break;
                        }
                        break;
                }
            }

I include several entities, now I want to order this query dynamically based on included properties, for example inventory in wallet. i tried dynamic linq library but it dont work for this situation;

How can I do this?

CodePudding user response:

I'm not entirely sure it's possible to do it fully dynamic without setting up a mapping between UserNavigationPropsForSort and a Wallet property.

What I've done is made your code a bit more concise and expandable:

            var query = TableNoTracking;
            query = query
                .Include(r => r.UserRoles).ThenInclude(o => o.Role)
                .Include(c => c.Photos.Where(x => x.IsMain))
                .Include(w => w.Wallets);
            
            if (!string.IsNullOrWhiteSpace(filterUser.SortBy.ToString()))
            {
                Func<Wallet, decimal> sortByToProperty = filterUser.SortBy switch
                {
                    UserNavigationPropsForSort.InventorySum => w => w.Inventory,
                    UserNavigationPropsForSort.InterMoneySum => w => w.InterMoney,
                    UserNavigationPropsForSort.ExitMoneySum => w => w.ExitMoney,
                    UserNavigationPropsForSort.OnExitMoneySum => w => w.OnExitMoney,
                    _ => throw new ArgumentOutOfRangeException()
                };

                query = filterUser.Reverse
                    ? query.OrderByDescending(x => x.Wallets.Select(sortByToProperty).Sum())
                    : query.OrderBy(x => x.Wallets.Select(sortByToProperty).Sum());
            }

If, at any point, you want to add more properties to sort by, you can expand the sortByToProperty switch.

Please let me know if this is what you meant.

CodePudding user response:

Credit to @nbokmans and @Svyatoslav Danyliv. I used Expression instead of Func and now code work.

        if (!string.IsNullOrWhiteSpace(filterUser.SortBy))
            {
                if (filterUser.SortableProperties.Any(x =>
                    string.Equals(x, filterUser.SortBy, StringComparison.CurrentCultureIgnoreCase)))
                {
                    Expression<Func<User, int>> exp = filterUser.SortBy switch
                    {
                        UserNavigationPropsForSort.InventorySum => w => w.Wallets.Select(x => x.Inventory).Sum(),
                        UserNavigationPropsForSort.InterMoneySum => w => w.Wallets.Select(x => x.InterMoney).Sum(),
                        UserNavigationPropsForSort.ExitMoneySum => w => w.Wallets.Select(x => x.ExitMoney).Sum(),
                        UserNavigationPropsForSort.OnExitMoneySum => w => w.Wallets.Select(x => x.OnExitMoney).Sum(),
                        _ => throw new ArgumentOutOfRangeException()
                    };

                    query = filterUser.Reverse ? query.OrderByDescending(exp) : query.OrderBy(exp);
                }
            }
  • Related