Zol*_*yak 8 c# linq lambda entity-framework
我想知道如何在列表中存储orderby表达式.这就是我想写的:
List<Expression<Func<Products,Object>>> list = new List<Expression<Func<Products,Object>>>()
{
p => p.Name,
p => p.Id
};
Run Code Online (Sandbox Code Playgroud)
然后:
var expr = list[0];
myProducts.OrderBy( expr );
Run Code Online (Sandbox Code Playgroud)
该工程p.Name
,但不工作p.Id
(list[1]
),因为它降低follwing例外
EntityFramework.SqlServer.dll中出现未处理的"System.NotSupportedException"类型异常附加信息:无法将类型"System.Int32"强制转换为"System.Object"类型.LINQ to Entities仅支持转换EDM原语或枚举类型.
我必须使用什么类型的列表?
这是我的解决方案(使用 Reflection 并基于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; }
}
Run Code Online (Sandbox Code Playgroud)
引入扩展方法以更轻松地从正常进行转换Expression
:
public static class ExpressionExtensions
{
public static ConvertableExpression<T> AsConvertable<T>(this Expression<Func<T, object>> expr)
{
return new ConvertableExpression<T>(expr);
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
myProducts.OrderBy(expr.AsConvertable());
Run Code Online (Sandbox Code Playgroud)