Linq表达式搜索过滤器给出错误对象引用未设置为对象的实例

时间:2018-04-01 06:31:09

标签: entity-framework linq expression

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值时它会给出错误。

2 个答案:

答案 0 :(得分:0)

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

Expression.And是按位的 - Expression.AndAlso是短路评估的逻辑和。

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

答案 1 :(得分:-1)

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