假设一个Type
数组作为条件对象,指示必须显示的子类型。
型号:
public abstract class Shape { }
public class Circle : Shape { }
public class Rectangle : Shape { }
我已经实现了一个应用此类查询的扩展方法
public static IQueryable<TSource> OfTypes<TSource, TResult>(
this IQueryable<TSource> source,
Expression<Func<TSource, TResult>> expression,
params Type[] types)
{
if (!types.Any())
{
return source;
}
Expression finalExpression = Expression.TypeIs(expression, types.First());
foreach (var type in types.Skip(1))
{
finalExpression = Expression.OrElse(
Expression.TypeIs(expression, type),
finalExpression);
}
var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(
finalExpression,
expression.Parameters);
return source.Where(lambdaExpression);
}
然后我可以像这样使用它
var types = new Type[] { typeof(Circle), typeof(Rectange) };
db.Shapres.OfTypes(s => s, types);
生成的表达式类似于
e => e is Circle || e is Rectange
正是我想要的但是我得到了这个错误
LINQ to Entities中不支持LINQ表达式节点类型“Lambda”。
即使我在扩展方法的最后一行使用了LinqKit的AsExpandable()
方法:
return source.AsExpandable().Where(lambdaExpression);
但同样的错误。
我也尝试了PredicateBuilder这样但又犯了同样的错误
var finalExpression = PredicateBuilder.False<TSource>();
foreach (var type in types)
{
var expressionParameter = Expression.Parameter(typeof(TSource), "it");
var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(
Expression.TypeIs(expression, type),
expressionParameter);
finalExpression.Or(lambdaExpression);
}
有什么问题?
如何在没有问题的情况下将EF中的Expression
转换为Expression<Func<T, TResult>>
?
或者我如何将Expression
实例传递给Where
扩展方法?
或者如何将Expression.TypeIs
用于EF?
答案 0 :(得分:1)
您需要将参数传递给Lambda函数,然后传递传入的表达式,即lambda。尝试通过删除'expression'参数来创建扩展方法内部的参数,因为它不需要。
public static IQueryable<TSource> OfTypes<TSource>(
this IQueryable<TSource> source,
params Type[] types)
{
if (!types.Any())
{
return source;
}
var param = Expression.Parameter(typeof(TSource), "p");
Expression finalExpression = Expression.TypeIs(param, types.First());
foreach (var type in types.Skip(1))
{
finalExpression = Expression.OrElse(
Expression.TypeIs(param, type),
finalExpression);
}
var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(
finalExpression, param);
return source.Where(lambdaExpression);
}
这样称呼:
var types = new Type[] { typeof(Circle), typeof(Rectangle) };
var test = context.Shapes.OfTypes(types);