'How to sort entity model by column name of display model in C# .NET Core using LINQ?

I have a page that displays all users in the table.

The front end uses a class that is different from the database model.

public class UserDetailsViewDto
{
    public long Id { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhoneNumber { get; set; }
    public bool EmailConfirmed { get; set; }
    public string Role { get; set; }
}

When the user chooses to sort by Role, the frontend sends string SortColum = "Role". I can map that to any other property but in this case, I need that to be User.UserRoles.FirstOrDefault().Role.Name

Query:

var users = Context.Users
                   .Include(user => user.UserRoles)
                       .ThenInclude(ur => ur.Role)
                   .ApplySort(string ParameterName)
                   .ToList();

The problem is: I must return a list of Users from the repository to a business layer of application where I do mapping to UserDetailsViewDto.

These are the extension methods I use to sort data:

public static IQueryable<T> ApplySort<T>(this IQueryable<T> source, QueryResource query)
{
    if (string.IsNullOrEmpty(query.SortColumn))
        return source;

    return source.OrderBy(query.SortColumn, query.SortDirection == "desc");
}

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string orderByProperty, bool desc)
{
    string command = desc ? "OrderByDescending" : "OrderBy";

    var type = typeof(T);
    var property = type.GetProperty(orderByProperty, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
    var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression));

    return source.Provider.CreateQuery<T>(resultExpression);
}

User is just an example, I have many other pages with a similar problem. How to solve this?

Is sending IQueryable from a repository and using ProjectTo() only solution?

Thanks.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source