How do I add more than two conditions to an Expression dynamically?

2

I need to pass a list of Expressions as a parameter and create the 'Ands' as dynamically as possible.

So, whenever I add a new Expression to the list, I will have to change the class that mounts Expression as well.

ParameterExpression c = Expression.Parameter(typeof(Boleto), "Boleto");
var temNegociacao = Expression.IsFalse(Expression.Property(c, "Negociacao"));
var status = Expression.IsTrue(Expression.Property(c, "Status"));
var bolsa = Expression.LessThan(Expression.Property(c, "Bolsa"), Expression.Constant(100.0));
var aberto = Expression.IsTrue(Expression.Property(c, "Aberto"));
var periodoLetivo = Expression.IsTrue(Expression.Property(c, "Periodo"));

Expression<Func<Billet, bool>> condition =
Expression.Lambda<Func<Billet, bool>>(
Expression.And(
Expression.And(temNegociacao,
Expression.And(status,
Expression.And(bolsa,
Expression.And(aberto, periodoLetivo)))), c));

return _dbSet.Where(condition).ToList();
    
asked by anonymous 21.08.2015 / 15:47

1 answer

2

Expression trees are valid ways to construct a predicate for use with the Entity Framework, but in this case I think you are complicating it.

Where returns IQueryable . The object that implements IQueryable is not necessarily a materialized list, so you can use Where multiple times if you want. For example:

return _dbSet.Where(x => !x.Negociacao)
             .Where(x => x.Status)
             .Where(x => x.Bolsa < 100)
             .Where(x => x.Aberto)
             .Where(x => x.Periodo)
             .ToList();

This returns the same thing as your expression, but has more readability.

Incidentally, try a test like the one below:

var sql = ((ObjectQuery)_dbSet.Where(x => !x.Negociacao)
             .Where(x => x.Status)
             .Where(x => x.Bolsa < 100)
             .Where(x => x.Aberto)
             .Where(x => x.Periodo)).ToTraceString();

sql will have an SQL statement. Then repeat for your expression assembly method. The result should be (almost) the same.

If the purpose is to assemble values according to what has been filled in, you can do this:

var sentenca = _dbSet.Where(x => !x.Negociacao);

if (algumaLogicaVerdadeira)
{
    sentenca = sentenca.Where(x => x.Status);
}

/* Aqui você monta sua regra de negócio. No final, devolva a lista */

return sentenca.ToList();
    
21.08.2015 / 16:54