Ich mochte die Antwort von @Mark Powell , aber wie @ShuberFu sagte, gibt es den Fehler LINQ to Entities only supports casting EDM primitive or enumeration types
.
Das Entfernen var propAsObject = Expression.Convert(property, typeof(object));
funktionierte nicht mit Eigenschaften, bei denen es sich um Werttypen handelte, wie z. B. Ganzzahl, da das int-Objekt nicht implizit eingerahmt wurde.
Unter Verwendung von Ideen von Kristofer Andersson und Marc Gravell habe ich einen Weg gefunden, die abfragbare Funktion unter Verwendung des Eigenschaftsnamens zu erstellen und sie weiterhin mit Entity Framework funktionieren zu lassen. Ich habe auch einen optionalen IComparer-Parameter eingefügt. Achtung: Der IComparer-Parameter funktioniert nicht mit Entity Framework und sollte bei Verwendung von Linq to Sql weggelassen werden.
Folgendes funktioniert mit Entity Framework und Linq to Sql:
query = query.OrderBy("ProductId");
Und @Simon Scheurer das funktioniert auch:
query = query.OrderBy("ProductCategory.CategoryId");
Und wenn Sie Entity Framework oder Linq to Sql nicht verwenden, funktioniert dies:
query = query.OrderBy("ProductCategory", comparer);
Hier ist der 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);
}
/// <summary>
/// Builds the Queryable functions using a TSource property name.
/// </summary>
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)
)
);
}
}