Entity Framework Order By Column Name as String
An extension method to filter a linq query with the field as a string
public static class EntityFrameworkExtensions
{
public static IOrderedQueryable OrderBy(this IQueryable query, string propertyName)
{
var entityType = typeof(TSource);
//Create x=>x.PropName
var propertyInfo = entityType.GetProperty(propertyName);
ParameterExpression arg = Expression.Parameter(entityType, "x");
MemberExpression property = Expression.Property(arg, propertyName);
var selector = Expression.Lambda(property, new ParameterExpression[] { arg });
//Get System.Linq.Queryable.OrderBy() method.
var enumarableType = typeof(System.Linq.Queryable);
var method = enumarableType.GetMethods()
.Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition)
.Where(m =>
{
var parameters = m.GetParameters().ToList();
return parameters.Count == 2;
}).Single();
//The linq's OrderBy<TSource, TKey> has two generic types, which provided here
MethodInfo genericMethod = method.MakeGenericMethod(entityType, propertyInfo.PropertyType);
// Call query.OrderBy(selector), with query and selector: x=> x.PropName
// Note that we pass the selector as Expression to the method and we don't compile it.
// By doing so EF can extract "order by" columns and generate SQL for it
var newQuery = (IOrderedQueryable)genericMethod.Invoke(genericMethod, new object[] { query, selector });
return newQuery;
}
public static IOrderedQueryable OrderByDescending(this IQueryable query, string propertyName)
{
var entityType = typeof(TSource);
//Create x=>x.PropName
var propertyInfo = entityType.GetProperty(propertyName);
ParameterExpression arg = Expression.Parameter(entityType, "x");
MemberExpression property = Expression.Property(arg, propertyName);
var selector = Expression.Lambda(property, new ParameterExpression[] { arg });
//Get System.Linq.Queryable.OrderBy() method.
var enumarableType = typeof(System.Linq.Queryable);
var method = enumarableType.GetMethods()
.Where(m => m.Name == "OrderByDescending" && m.IsGenericMethodDefinition)
.Where(m =>
{
var parameters = m.GetParameters().ToList();
return parameters.Count == 2;
}).Single();
//The linq's OrderByDescending<TSource, TKey> has two generic types, which provided here
MethodInfo genericMethod = method.MakeGenericMethod(entityType, propertyInfo.PropertyType);
// Call query.OrderByDescending(selector), with query and selector: x=> x.PropName
// Note that we pass the selector as Expression to the method and we don't compile it.
// By doing so EF can extract "order by" columns and generate SQL for it
var newQuery = (IOrderedQueryable)genericMethod.Invoke(genericMethod, new object[] { query, selector });
return newQuery;
}
}
The order by can then be called as follows:
query = query.OrderBy("ProductName");