Thursday 27 August 2009

SELECT * FROM <table> WHERE <campos> IN (<lista>) em LINQ

SELECT * FROM <table> WHERE <campos> IN (<lista>) em LINQ

Uma operação que parece relativamente simples, afinal não é. Se tivermos uma lista (string[]) e, usando o LINQ, quisermos cruzar com um SELECT temos que fazer o seguinte:

Copiar este método para o nosso projecto:

        static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
        {
            if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
            if (null == values) { throw new ArgumentNullException("values"); }
            ParameterExpression p = valueSelector.Parameters.Single();
            // p => valueSelector(p) == values[0] || valueSelector(p) == ...
            if (!values.Any())
            {
                return e => false;
            }
            var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
            var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
            return Expression.Lambda<Func<TElement, bool>>(body, p);
        }

e fazer o seguinte:

        IQueryable<string> results =
                    (from e in myTable.Where(BuildContainsExpression<string, string>(e => e, stringArray))
                     select e);
        results.ToList();


Só assim consigo fazer correctamente um SELECT * FROM <table> WHERE <campos> IN (<lista>) usando LINQ