C# lambda中的动态where子句
我正在使用实体框架,我需要创建一个动态表达式,如:C# lambda中的动态where子句,c#,lambda,C#,Lambda,我正在使用实体框架,我需要创建一个动态表达式,如: var sel = Expression.Lambda<Func<TEntity, bool>>(propertyAccess, parameter); var compiledSel = sel.Compile(); // sel = x.Name // filter.Value = "John" Repository.GetData.Where(item => compiledSel(item) != null
var sel = Expression.Lambda<Func<TEntity, bool>>(propertyAccess, parameter);
var compiledSel = sel.Compile();
// sel = x.Name
// filter.Value = "John"
Repository.GetData.Where(item => compiledSel(item) != null && compiledSel(item).ToLower().StartsWith(filter.Value.ToString().ToLower()))
到,例如
x => x.Name != null && x.Name.StartsWith("John")
我这样做的原因是因为我有多个实体,我希望能够动态过滤
有什么建议吗
编辑:
针对EF的查询本身在此处运行:
private IList<TEntity> GetCollection(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, object>>[] includes)
{
return DbSet
.Where(where)
.ApplyIncludes(includes)
.ToList();
}
private IList GetCollection(表达式,其中,表达式[]包括)
{
返回数据集
.Where(Where)
.ApplyIncludes(包括)
.ToList();
}
当我现在运行查询时,data where子句是
Param_0=>((Invoke(value(..
和I getLINQ to Entities中不支持LINQ表达式节点类型“Invoke”。
error动态LINQ可能是您的一个选项:
Repository.People.Where("Name != null && Name.StartsWith(\"John\")")
首先,如果
propertyAccess
是字符串属性的访问器,则
var sel = Expression.Lambda<Func<TEntity, bool>>(propertyAccess, parameter);
以下是所用帮助器方法的代码:
public static class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
如何向您的实体添加一个接口?例如,
class MyEntity:INameable
带有属性string Name
,然后您可以使用Func
动态propertyaaccess
变量包含哪些内容?字符串属性访问器?因此sel
实际上是Expression
而不是Expressionn
如示例中所示?添加不可数的问题在于,我有许多不同的实体,因此“x.Name”只是一个示例,它可能是相当多的其他内容。在这个示例中,propperyAccess包含一个MemberExpression{x.Name}我很确定您使用的是重载IEnumerable.Where(Func)
重载,它接受一个Func
而不是IQueryable。其中(表达式)
接受一个表达式。您的问题不是“它与IQueryable一起工作,但与EF不一起工作”。
var sel = Expression.Lambda<Func<TEntity, string>>(propertyAccess, parameter);
var selector = Expression.Lambda<Func<TEntity, string>>(propertyAccess, parameter);
var value = filter.Value.ToString().ToLower();
Expression<Func<string, bool>> prototype =
item => item != null && item.ToLower().StartsWith(value);
var predicate = Expression.Lambda<Func<T, bool>>(
prototype.Body.ReplaceParameter(prototype.Parameters[0], selector.Body),
selector.Parameters[0]);
public static class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}