0

I have a UI grid which permits sorting by column :

Id Organisation Name Organisation type Departments
1 first some type def
2 second another type abc, def
2 third some type xyz

See the entities below:

public class Organisation
{
    public int Code { get; set; }
    public string Type { get; set; }
    public string Name { get; set; }
    public List<Department> Departments { get; set; }
}

public class Department
{
    public int Code { get; set; }
    public string Name { get; set; }
}

I want to be able to sort the table values by Departments which is a comma separated values that comes from Organization.Departments.Select(p=> p.Name); I would like to make the sorting as an IQueryable and avoid bringing all the data in memory because After sorting I will apply the pagination and I don't want to bring all the DB records in memory.

I'm using the following extension method for sorting, but it is not working for nested collections:

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortProperty, ListSortDirection sortOrder)
{
            var type = typeof(T);
            var property = type.GetProperty(sortProperty, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

            if (property == null)
                throw new OperationFailedException($"Sorting by {sortProperty}");

            var parameter = Expression.Parameter(type, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var orderByExp = Expression.Lambda(propertyAccess, parameter);
            var typeArguments = new Type[] { type, property.PropertyType };
            var methodName = sortOrder == ListSortDirection.Ascending ? "OrderBy" : "OrderByDescending";
            var resultExp = Expression.Call(typeof(Queryable), methodName, typeArguments, source.Expression, Expression.Quote(orderByExp));

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

This method works fine for properties that are at object level.

IQueryable I'm using later for sorting looks something like this:

var iQueryableToBeSorted = _dbContext.Organization.Include(p=>p.Departments).AsQueryable();
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • What is your IQueryable and how you build it? your problem is not about fixing sort extension method. it should be sorted in linq query. – sa-es-ir Sep 14 '21 at 10:41
  • I would like to have the list sorted only then the user ask for by clicking on the sorting arrow from the grid header. So it should allow ascending and descending sorting on demand. – user4117572 Sep 14 '21 at 10:46
  • That's not a list of objects, that's a weird string. This is a critical database design bug that *can't* be fixed by ORMs like EF Core. You can't query, filter, order or index the substrings in that string in SQL. No matter what you do on the *client* doesn't change the fact that on the database, this is just a single string value – Panagiotis Kanavos Sep 14 '21 at 10:59
  • It is not saved as a string in DB. I have different tables for Organization and Departments. Only that the client is asking for displaying them as a comma separated values in the grid. – user4117572 Sep 14 '21 at 11:02
  • Fix the bug. Use a separate table for `Departments`. This will allow you to add the inevitable extra fields you'll want to add for those departments, eg description, address etc. This will also help prevent duplicate or misspelled entries. It will make changing an organisation's departments infinitely easier. – Panagiotis Kanavos Sep 14 '21 at 11:02
  • @user4117572 `It is not saved as a string in DB.` but that's what you posted and what the screenshot shows. What is the *actual* question, actual query, actual tables then? What's the purpose of that `OrderBy` code? LINQ's `OrderBy` is already generic – Panagiotis Kanavos Sep 14 '21 at 11:03
  • As I mentioned before, there is a separate table for Departments in DB, the table I draw in the question description is the grid I'm displaying in UI. – user4117572 Sep 14 '21 at 11:06
  • If the question is `How can I order results using a field list stored in a table` the answer is `You can't do that in SQL`. Did you copy [this answer](https://stackoverflow.com/questions/36298868/how-to-dynamically-order-by-certain-entity-properties-in-entity-framework-7-cor)? – Panagiotis Kanavos Sep 14 '21 at 11:06
  • @PanagiotisKanavos thanks for your answer. Do you have any solution for this types of situations or you are suggesting to bring the entire table in memory for further sorting operations? :) – user4117572 Sep 14 '21 at 11:16
  • Just imagine how you'd do this in SQL, because that's what you ask EF to do. Can't be done without flattening the departments names *in SQL*. There's no way to make EF do this. Create a view containing the processed column and map a query to the view. – Gert Arnold Sep 14 '21 at 11:26

0 Answers0