Tôi thích câu trả lời từ @Mark Powell , nhưng như @ShuberFu đã nói, nó đưa ra lỗi LINQ to Entities only supports casting EDM primitive or enumeration types
.
Việc xóa var propAsObject = Expression.Convert(property, typeof(object));
không hoạt động với các thuộc tính có kiểu giá trị, chẳng hạn như số nguyên, vì nó sẽ không hoàn toàn đóng hộp đối tượng int to.
Sử dụng Ý tưởng từ Kristofer Andersson và Marc Gravell, tôi đã tìm ra cách để xây dựng hàm Queryable bằng cách sử dụng tên thuộc tính và nó vẫn hoạt động với Entity Framework. Tôi cũng bao gồm một tham số IComparer tùy chọn. Thận trọng: Tham số IComparer không hoạt động với Entity Framework và nên bị loại bỏ nếu sử dụng Linq to Sql.
Phần sau hoạt động với Entity Framework và Linq to Sql:
query = query.OrderBy("ProductId");
Và @Simon Scheurer điều này cũng hoạt động:
query = query.OrderBy("ProductCategory.CategoryId");
Và nếu bạn không sử dụng Entity Framework hoặc Linq to Sql, điều này sẽ hoạt động:
query = query.OrderBy("ProductCategory", comparer);
Đây là mã:
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)
)
);
}
}