I liked @Mark Powell's answer, but as @ShuberFu said, it throws an error, LINQ to Entities only supports casting EDM primitive or enumeration types .
Removing var propAsObject = Expression.Convert(property, typeof(object)); didn't work with properties that are value types, such as integer ones, since it would not implicitly put an int in an object.
Using the ideas of Christopher Andersson and Mark Gravell, I found a way to construct the Queryable function using the property name and still work with the Entity Framework. I also included the optional IComparer parameter. Note: IComparer does not work with Entity Framework and should be skipped when using Linq to Sql.
The following works with Entity Framework and Linq to Sql:
query = query.OrderBy("ProductId");
And @Simon Scheurer this also works:
query = query.OrderBy("ProductCategory.CategoryId");
And if you are not using Entity Framework or Linq to Sql, this works:
query = query.OrderBy("ProductCategory", comparer);
Here is the code:
public static class IQueryableExtensions { public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName, IComparer<object> comparer = null) { return CallOrderedQueryable(query, "OrderBy", propertyName, comparer); } public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName, IComparer<object> comparer = null) { return CallOrderedQueryable(query, "OrderByDescending", propertyName, comparer); } public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> query, string propertyName, IComparer<object> comparer = null) { return CallOrderedQueryable(query, "ThenBy", propertyName, comparer); } public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> query, string propertyName, IComparer<object> comparer = null) { return CallOrderedQueryable(query, "ThenByDescending", propertyName, comparer); }