我想知道如何在列表中存储orderby表达式。这就是我想写的:
List<Expression<Func<Products,Object>>> list = new List<Expression<Func<Products,Object>>>()
{
p => p.Name,
p => p.Id
};
然后:
var expr = list[0];
myProducts.OrderBy( expr );
适用于p.Name
,但不适用于p.Id
(list[1]
),因为它会删除异常
未处理的类型&#39; System.NotSupportedException&#39;发生在EntityFramework.SqlServer.dll中 附加信息:无法转换类型&System; Int32&#39;键入&#39; System.Object&#39;。 LINQ to Entities仅支持转换EDM原语或枚举类型。
我必须使用哪种类型的列表?
答案 0 :(得分:1)
这是我的解决方案(使用反思并基于DynamicLinq提示):
定义ConvertableExpression
课程,以便我们拦截对自定义OrderBy()
的调用:
public class ConvertableExpression<T>
{
public ConvertableExpression(Expression<Func<T, object>> expr)
{
this.Expression = expr;
}
public Expression<Func<T, object>> Expression { get; private set; }
}
引入扩展方法,以便从普通Expression
:
public static class ExpressionExtensions
{
public static ConvertableExpression<T> AsConvertable<T>(this Expression<Func<T, object>> expr)
{
return new ConvertableExpression<T>(expr);
}
}
使用基于反射的IQueryable
实现扩展OrderBy()
:
public static class QueryableExtensions
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, ConvertableExpression<T> expr)
{
Expression queryExpr = source.Expression;
var exprBody = SkipConverts(expr.Expression.Body);
var lambda = Expression.Lambda(exprBody, expr.Expression.Parameters);
var quote = Expression.Quote(lambda);
queryExpr = Expression.Call(typeof(Queryable), "OrderBy", new[] { source.ElementType, exprBody.Type }, queryExpr, quote);
return (IOrderedQueryable<T>)source.Provider.CreateQuery(queryExpr);
}
private static Expression SkipConverts(Expression expression)
{
Expression result = expression;
while (result.NodeType == ExpressionType.Convert || result.NodeType == ExpressionType.ConvertChecked)
result = ((UnaryExpression)result).Operand;
return result;
}
}
用法:
myProducts.OrderBy(expr.AsConvertable());
答案 1 :(得分:0)
因此看起来像EF的OrderBy的实现通过检查是否&lt; T&gt; 是一个结构或对象,所以你告诉它调用 OrderBy&lt; ...,object&gt;(someStructTypeVariable)
作为一种解决方法,我会劝你存储整个代表而不是表达。
试试这个:
internal static class MyExtensions
{
public static IOrderedQueryable<TSource> OrderBy<TSource, TField>(this IQueryable<TSource> source, Expression<Func<TSource, TField>> selector, bool descending)
{
return descending
? source.OrderByDescending(selector)
: source.OrderBy(selector);
}
}
var orderers = new List<Func<IQueryable<Products>, IOrderedQueryable<Products>>>()
{
source => source.OrderBy(x => x.Id, true),
source => source.OrderBy(x => x.Id, false),
source => source.OrderBy(x => x.Name, false)
};
// To be replaced with entity source-collection.
IQueryable<Products> dummySource = new EnumerableQuery<MyType>(new List<Products>());
orderers[0](dummySource.Where(x => x.Id != 0));
答案 2 :(得分:0)
试试这个
List<Func<Products, Object>> list = new List<Func<Products, Object>>()
{
new Func<Products,Object>( p => p.Name),
new Func<Products,Object>( p => p.Id),
};