tags:

views:

707

answers:

1

Hi,

I would like to know how to be able to make an Expression tree by inputting more than one parameter

Example:

dataContext.Users.Where(u => u.username == "Username" && u.password == "Password")

At the moment the code that I did was the following but would like to make more general in regards whether the condition is OR or AND

public Func<TLinqEntity, bool> ANDOnlyParams(string[] paramNames, object[] values)
    {
        List<ParameterExpression> paramList = new List<ParameterExpression>();
        foreach (string param in paramNames)
        {
            paramList.Add(Expression.Parameter(typeof(TLinqEntity), param));
        }

        List<LambdaExpression> lexList = new List<LambdaExpression>();
        for (int i = 0; i < paramNames.Length; i++)
        {
            if (i == 0)
            {
                Expression bodyInner = Expression.Equal(
                                    Expression.Property(
                                        paramList[i], paramNames[i]),
                                        Expression.Constant(values[i]));
                lexList.Add(Expression.Lambda(bodyInner, paramList[i]));
            }
            else
            {
                Expression bodyOuter = Expression.And(
                                    Expression.Equal(
                                    Expression.Property(
                                    paramList[i], paramNames[i]),
                                    Expression.Constant(values[i])),
                                    Expression.Invoke(lexList[i - 1], paramList[i]));
                lexList.Add(Expression.Lambda(bodyOuter, paramList[i]));
            }
        }

        return ((Expression<Func<TLinqEntity, bool>>)lexList[lexList.Count - 1]).Compile();
    }

Thanks

+3  A: 

Expression.And is the wrong thing to use here, it's the bitwise and. You want AndAlso.

It seems like you aside from that you already know the mechanics of how to build the expression tree. So what you're really asking is how can you let the caller of your building-method specify a more complicated, flexible way of combining different conditions.

Ultimately for true flexibility you need a mini query language. Parse the language to build the expression tree.

In the short term, you might get by with something much simpler: a list of primitive expressions and a bool flag to say whether they should be combined with && or ||.

Update - I notice you're actually compiling the resulting expression into a real delegate. This makes me wonder why you're doing this the hard way in the first place. Why not just write the expression as a lambda, as in your initial example? (If you're using Linq to SQL or EF, you shouldn't be compiling the expression anyway.)

Update 2 - What you probably need is Dynamic Linq.

Daniel Earwicker
Regarding why I am going with the hard way (returning a delegate), the reason is don't have direct access to the database column names at design time. And I can't access using the datacontext.table.Where(...); because I have the table names encrypted inside the database.Thanks for your answer I will look for the AndAlso method...
Ryan
@Ryan - see update - I remembered the library that does this!
Daniel Earwicker
Thanks Daniel...I really appreciate it looks like exactly what I need :)
Ryan