1

I am new to linq c# , Following is my function

public static IQueryable<T> BuildWhereExpression<T>(this IQueryable<T> query, SearchAttributes searchModel)
    {
        string FilterField = searchModel.FilterField;
        string FilterOperator = searchModel.FilterOperator;
        string FilterValue = searchModel.FilterValue;
        ParameterExpression ParamExp = Expression.Parameter(typeof(T), GlobalConstants.SearchExpressionName);
        Expression InitialExp;
        LambdaExpression FinalExp;

        switch (FilterOperator)
        {
            case GlobalConstants.IsEqualTo:
                if (FilterValue == "")
                    InitialExp = Expression.Call(Expression.PropertyOrField(ParamExp, FilterField), typeof(string).GetMethod("Contains"), Expression.Constant(FilterValue));
                else
                    InitialExp = Expression.Equal(Expression.PropertyOrField(ParamExp, FilterField), Expression.Constant(FilterValue));
                break;

            case GlobalConstants.Contains:
                { // This is what i havd tried till now
                    //var Column = Expression.PropertyOrField(ParamExp, FilterField);
                    //var isNull = Expression.Equal(Column, Expression.Constant(null));

                    //Expression left = Expression.Call(Column, typeof(string).GetMethod("ToString", System.Type.EmptyTypes));
                    //Expression left = Expression.Call(pe)
                }
                InitialExp = Expression.Call(Expression.PropertyOrField(ParamExp, FilterField), typeof(string).GetMethod("Contains"), Expression.Constant(FilterValue));
                break;

            case GlobalConstants.StartsWith:
                InitialExp = Expression.Call(Expression.PropertyOrField(ParamExp, FilterField), typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }), Expression.Constant(FilterValue));
                break;

            default:
                InitialExp = Expression.Constant(true);
                break;
        }
        FinalExp = Expression.Lambda<Func<T, bool>>(InitialExp, new ParameterExpression[] { ParamExp });
        MethodCallExpression result = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, query.Expression, Expression.Quote(FinalExp));

        return query.Provider.CreateQuery<T>(result);
    }

The above code adds a condition for contains in a column dynamically. Contains does not works for column containing null values. How can i implement following logic

If table.ColumnValue is Null replace the column null with empty string then compair with the value in FilterValue

EDIT: I mean how can i implement query as coalesce(table.column,string.empty) == FilterValue

Please help me over this. Thanks in advance.

5
  • Contains does not works for column containing null values care to explain? Why shouldn't it work? Commented Mar 18, 2015 at 10:30
  • new List<string> { "x", null, "y" }.Contains("y") will return true, what is the problem? Commented Mar 18, 2015 at 10:34
  • @decoherence He is doing a query on a db... It is a little different, but it does work. Commented Mar 18, 2015 at 10:35
  • 1
    new List<string> { "x", null, "y" }.Contains(String.Empty) must return true in my case. Commented Mar 18, 2015 at 10:35
  • List doesn't mess with the values you provide and null is a value allowed for string. You could write a list implementation that changes null values to string.empty on your own though Commented Mar 18, 2015 at 10:39

1 Answer 1

3

The expression you are looking for is something like:

Expression<Func<T, bool>> exp = x => (x.FilterField ?? string.Empty).Contains(FilterValue);

that can be obtained with

var coalesce = Expression.Coalesce(
    Expression.PropertyOrField(ParamExp, FilterField),
    Expression.Constant(string.Empty))

so

InitialExp = Expression.Call(coalesce, typeof(string).GetMethod("Contains"), Expression.Constant(FilterValue));

Note that, considering future-proofing, I would always explicitly tell the .NET the parameters of the method I'm looking for:

typeof(string).GetMethod("Contains", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string) }, null);

because you can't know if, in .NET ∞.0, they'll finally add an overload that supports a StringComparison :-)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.