【问题标题】:Linq Expression search filter giving error Object reference not set to an instance of an objectLinq 表达式搜索过滤器给出错误对象引用未设置为对象的实例
【发布时间】:2018-04-01 06:31:09
【问题描述】:
public static Expression<Func<T, bool>> SearchExpression<T>(string[] propertyNames, string[] propertyValue){
    var parameterExp = Expression.Parameter(typeof(T), "type");
    MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", Type.EmptyTypes);
    MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
    List<Expression> methodCalls = new List<Expression>();
    Expression finalExpression = Expression.Constant(true);

    foreach (string propertyName in propertyNames)
    {
        var propertyExp = Expression.Property(parameterExp, propertyName);
        var queryValue = Expression.Constant(propertyValue[Array.IndexOf(propertyNames, propertyName)].ToLower(), typeof(string));
        var exp = Expression.NotEqual(propertyExp, Expression.Constant(null, typeof(object)));
        methodCalls.Add(exp);
        var toLowerMethodExp = Expression.Call(propertyExp, toLowerMethod);
        var containsMethodExp = Expression.Call(toLowerMethodExp, "Contains", Type.EmptyTypes, queryValue);
        methodCalls.Add(containsMethodExp);
    }
    var orExp = methodCalls.Aggregate((left, right) => Expression.And(left, right));
    return Expression.Lambda<Func<T, bool>>(orExp, parameterExp);
}

当我尝试调试它时,它显示了完美的表达式,但是当 db 列中有 null 值时它会给出错误。

【问题讨论】:

  • @marc_s 这不像其他问题那样简单的NullReferenceException,而且那里的答案都没有真正的帮助。这是与 AndAndAlso 相关的 LINQ 表达式特定问题。

标签: entity-framework linq expression


【解决方案1】:

您应该使用Expression.AndAlso 来组合方法调用。

Expression.And 是按位与,Expression.AndAlso 是短路评估逻辑与。

https://msdn.microsoft.com/en-us/library/bb353520(v=vs.110).aspx

【讨论】:

    【解决方案2】:
    public static Expression<Func<T, bool>> Search<T>(string[] propertyNames, string[] propertyValue,bool isOr = false)
            {
                ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
                MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
                var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                  .Where(p => p.PropertyType == typeof(string) && propertyNames.Contains(p.Name));
    
    
                Expression orExpressions = null;
                MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", Type.EmptyTypes);
                foreach (var callContainsMethod in from property in publicProperties
                                                   let myProperty = Expression.Property(parameter, property.Name)
                                                   let toLowerMethodExp = Expression.Call(myProperty, toLowerMethod)
                                                   let myExpression = Expression.Call(toLowerMethodExp, "Contains", null, Expression.Constant(propertyValue[Array.IndexOf(propertyNames, property.Name)].ToLower()))
                                                   let myNullExp = Expression.Call(typeof(string), (typeof(string).GetMethod("IsNullOrEmpty")).Name, null, myProperty)
                                                   let myNotExp = Expression.Not(myNullExp)
                                                   select new { myExpression, myNotExp })
                {
                    var andAlso = Expression.AndAlso(callContainsMethod.myNotExp, callContainsMethod.myExpression);
                    if (orExpressions == null)
                    {
                        orExpressions = andAlso;
                    }
                    else
                    {
                        if(!isOr)
                            orExpressions = Expression.And(orExpressions, andAlso);
                        else
                          orExpressions = Expression.Or(orExpressions, andAlso);
                    }
                }
                return Expression.Lambda<Func<T, bool>>(orExpressions, parameter);
            }
    

    【讨论】:

    • Err.. 你接受了我的答案,将其放入你的代码中,将其作为答案发布并接受它!?!此外,您搞砸了并重新引入了按位的 AndOr 表达式,它们不起作用。您是否接受我的回答,这将帮助其他遇到此问题的人并删除这个除了您自己之外什么都没有增加的人?
    • @IanMercer 我已经根据我的工作需要实现了代码,您的解决方案适用于我根据需要修改的多个属性和单个查询。我需要它用于多个查询和属性。是的,我同意我从您的代码中得到了解决方案。但我已经修改了。我已经检查过它工作正常。
    • 不能适用于多个属性,您使用的是逐位AndOr,而您应该使用AndAlsoOrElse。此外,Aggregate 是将表达式聚合为一个的更简洁的方法。
    猜你喜欢
    • 2020-06-12
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 2011-07-09
    • 2012-08-31
    • 2011-11-21
    相关资源
    最近更新 更多