July 16 2014

Dynamic LINQ - Using strings to sort by properties and child object properties

I stumbled across the Dynamic LINQ Library today and can't figure out why more people aren't talking about it.

It's an awesome little library that allows you to dynamically generate LINQ expressions from strings, which is perfect for things like sorting collections by object property values passed as querystring parameters to web api controllers, it even allows you to sort by child object property values!


Dynamic LINQ Installation

You can install Dynamic LINQ via NuGet with this command:

install-package System.Linq.Dynamic

 

The Dynamic LINQ library contains a set of extension methods for the IQueryable interface including this OrderBy() extension that accepts a LINQ expression as a string argument:

public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values);

The argument can be the property name that you want to sort by or a child object property. In this example I'm sorting a collection of Claim objects, so to sort the collection by the Claim.CreateDate property I pass the string "CreateDate", or to sort by the Claim.Dealer.DealerName child object property I pass the string "Dealer.DealerName".

To reverse the sort direction you append the string " descending" to the ordering argument, I extended this slightly further to enable setting the sort direction with an optional boolean value instead:

public static IQueryable Sort(this IQueryable collection, string sortBy, bool reverse = false)
{
    return collection.OrderBy(sortBy + (reverse ? " descending" : ""));
}


Sorting With Dynamic LINQ

I call the above extension method like this from my Web API controller:

public class ClaimsController : ApiController
{
    private IClaimService _claimService { get; set; }

    public ClaimsController(IClaimService claimService)
    {
        _claimService = claimService;
    }

    public IHttpActionResult Get(string sortBy = "CreateDate", bool reverse = false)
    {
        var claims = _claimService.Get();
            
        // sort using dynamic linq extension method
        claims = claims.Sort(sortBy, reverse);

        return Ok(claims);
    }
}


Sorting Without Dynamic LINQ 

As you can see the above is a HUGE improvement on what I had previously:

// sort expression
Expression<Func<Claim, object>> sortExpression;
switch (sortBy)
{
    case "Id":
        sortExpression = (x => x.Id);
        break;
    case "CreateDate":
        sortExpression = (x => x.CreateDate);
        break;
    case "Dealer.DealerName":
        sortExpression = (x => x.Dealer.DealerName);
        break;
    case "ClaimType.ClaimTypeName":
        sortExpression = (x => x.ClaimType.ClaimTypeName);
        break;
    case "ClaimReason":
        sortExpression = (x => x.ClaimReason);
        break;
    case "ClaimStatus.ClaimStatusName":
        sortExpression = (x => x.ClaimStatus.ClaimStatusName);
        break;
    case "Part":
        sortExpression = (x => x.Part);
        break;
    case "OrderNo":
        sortExpression = (x => x.OrderNo);
        break;
    case "ClaimQuantity":
        sortExpression = (x => x.ClaimQuantity);
        break;
    case "UnitCost":
        sortExpression = (x => x.UnitCost);
        break;
    case "QuantityCharged":
        sortExpression = (x => x.QuantityCharged);
        break;
    case "QuantityReceived":
        sortExpression = (x => x.QuantityReceived);
        break;
    case "QuantityReturned":
        sortExpression = (x => x.QuantityReturned);
        break;
    default:
        sortExpression = (x => x.CreateDate);
        break;
}

// sort direction
if (reverse)
    claims = claims.OrderByDescending(sortExpression).AsQueryable();
else
    claims = claims.OrderBy(sortExpression).AsQueryable();

 

More info on the Dynamic LINQ Library can be found at https://github.com/kahanu/System.Linq.Dynamic


Sponsored by