Generic Func needed to perform sorting of Entity Framework collection

Viewed 38

I have a grid with columns. When the grid column header is selected I post/ajax to server with header selected to return x rows.

In the following code, RefNo is integer while ProposalSectionNumber is a string.

How to make a generic function taking a string but return a Func to be used in the linq statement?

if (sort.dir == SortDirection.Asc)
{
    switch (sort.field)
    {
        case "RefNo":
            qry = qry.OrderBy(x => x.RefNo);
            break;
        case "ProposalSectionNumber":
            qry = qry.OrderBy(x => x.ProposalSectionNumber);
            break;                     
    }
}
else
{
    switch (sort.field)
    {
        case "RefNo":
            qry = qry.OrderByDescending(x => x.RefNo);
            break;
        case "ProposalSectionNumber":
            qry = qry.OrderByDescending(x => x.ProposalSectionNumber);
            break;

    }
}

I would like to do something like string sortOrder = "RefNo" var sortfunc = SortFunc(sortOrder)

if (sort.dir == SortDirection.Asc)
{
   qry = qry.OrderBy(sortFunc)
}
else
{
   qry = qry.OrderByDesc(sortFunc)
}

I have struggled creating the function SortFunc (which returns based on string or integer)

What is the best way to achieve this?

1 Answers

The problem with declaring a type for sortFunc is that it depends on the type of the field by which you sort. If all fields were of the same type, say, all strings, you could use the type of Expression<Func<MyEntity,string>> for your sortFunc variable.

There is another way of removing code duplication when sort fields do not share a common type. Introduce a generic helper method that takes sort order as a parameter, and call it instead of OrderBy/OrderByDescending:

private static IOrderedQueryable<T> AddOrderBy<T,TKey>(
    IQueryable<T> orig
,   Expression<Func<T,TKey>> selector
,   bool isAscending
) {
    return isAscending ? orig.OrderBy(selector) : orig.OrderByDescending(selector);
}

Now you can rewrite your code as follows:

var isAscending = (sort.dir == SortDirection.Asc);
switch (sort.field) {
    case "RefNo":
        qry = qry.AddOrderBy(x => x.RefNo, isAscending);
        break;
    case "ProposalSectionNumber":
        qry = qry.AddOrderBy(x => x.ProposalSectionNumber, isAscending);
        break;                     
}
Related