c# - lambda 中的动态 where 子句

标签 c# lambda

我正在使用 Entity Framework ,我需要创建一个动态表达式,例如:

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,但我需要它才能与 Entity Framework 一起使用。

这意味着我需要解析

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 LINQ to Entities 不支持。 错误

最佳答案

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

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

应该是

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

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

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

关于c# - lambda 中的动态 where 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39205653/

相关文章:

c# - Windows 手机 7 - 仅限 C#?

c# - C# 中的自然排序顺序 - 实现

c# - 无法将扩展类转换为 IList

java - 使用 Lambda 表达式将列表转换为 map 不起作用

java - 为什么 hankcs/AhoCorasickDoubleArrayTrie 中的 lambda 示例不起作用?

c# - JSON反序列化将负值转换为绝对值

c# - DurandalAuth 2.0.1 的 Weyland 构建失败

c++ - 是否可以更改此代码以避免使用 C++ lambda 表达式?

java - 什么时候大括号在 Java 8 lambda 语法中是可选的?

Java 8 如何使用 lambda 表达式简化 for 循环