lambda

时间:2016-08-29 11:51:32

标签: 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 && compiledSel(item).ToLower().StartsWith(filter.Value.ToString().ToLower()))

以上适用于IQueriable,但我需要它与实体框架一起使用。

这意味着我需要解析

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();
}

当我现在运行查询时,数据where子句为Param_0 => (((Invoke(value(....并且我得到The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.错误

2 个答案:

答案 0 :(得分:3)

首先,如果propertyAccess是字符串属性的访问者,则以下

var sel = Expression.Lambda<Func<TEntity, bool>>(propertyAccess, parameter);

应该是

var sel = Expression.Lambda<Func<TEntity, string>>(propertyAccess, parameter);

其次,Compile在EF表达式中不起作用。您可以使用Expression类的方法手动构建整个谓词表达式,但这相对较难。我建议你使用“原型”表达式和简单的参数替换器,如下所示:

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);
        }
    }
}

答案 1 :(得分:1)

Dynamic Linq可能是您的选择:

Repository.People.Where("Name != null && Name.StartsWith(\"John\")")

https://www.nuget.org/packages/System.Linq.Dynamic