J'ai aimé la réponse de @Mark Powell , mais comme @ShuberFu l'a dit, cela donne l'erreur LINQ to Entities only supports casting EDM primitive or enumeration types
.
La suppression var propAsObject = Expression.Convert(property, typeof(object));
ne fonctionnait pas avec les propriétés qui étaient des types valeur, tels que des entiers, car elle ne mettrait pas implicitement l'int en objet.
En utilisant les idées de Kristofer Andersson et Marc Gravell, j'ai trouvé un moyen de construire la fonction Queryable en utilisant le nom de la propriété et de la faire fonctionner avec Entity Framework. J'ai également inclus un paramètre IComparer facultatif. Attention: le paramètre IComparer ne fonctionne pas avec Entity Framework et doit être omis si vous utilisez Linq to Sql.
Ce qui suit fonctionne avec Entity Framework et Linq to Sql:
query = query.OrderBy("ProductId");
Et @Simon Scheurer cela fonctionne également:
query = query.OrderBy("ProductCategory.CategoryId");
Et si vous n'utilisez pas Entity Framework ou Linq to Sql, cela fonctionne:
query = query.OrderBy("ProductCategory", comparer);
Voici le 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);
}
public static IOrderedQueryable<T> CallOrderedQueryable<T>(this IQueryable<T> query, string methodName, string propertyName,
IComparer<object> comparer = null)
{
var param = Expression.Parameter(typeof(T), "x");
var body = propertyName.Split('.').Aggregate<string, Expression>(param, Expression.PropertyOrField);
return comparer != null
? (IOrderedQueryable<T>)query.Provider.CreateQuery(
Expression.Call(
typeof(Queryable),
methodName,
new[] { typeof(T), body.Type },
query.Expression,
Expression.Lambda(body, param),
Expression.Constant(comparer)
)
)
: (IOrderedQueryable<T>)query.Provider.CreateQuery(
Expression.Call(
typeof(Queryable),
methodName,
new[] { typeof(T), body.Type },
query.Expression,
Expression.Lambda(body, param)
)
);
}
}