Crie consultas dinâmicas com Predicated Builder

Standard

C# 4.0 in a Nutshell

Vamos falar neste artigo sobre um recurso muito utilizado e que ajuda muito o trabalho para criação de cosultas dinâmicas com Linq chamado Predicated Builder.

Predicated Builder é uma biblioteca gratuita desenvolvida por Josefh Albahari e Ben Albahari (Experts em C# por sinal) que viabiliza a criação de queries dinâmicas para consultas com Linq. Sua utilização é muito simples e possui um código bem limpo e fácil.

Veja abaixo um exemplo de uma querie com Linq de forma tradicional:

int codEmpresa = 1;
string nome = "Caixa";
DB _db = new DB();

var lista = _db.Produtos.Where(p => p.CodEmpresa = codEmpresa && p.Nome.Contains(nome));

Agora veja a mesma querie com Predicated Builder:

int codEmpresa = 1;
string nome = "Caixa";
DB _db = new DB();

//Cláusula where
var where = PredicateBuilder.True<Produto>();

where = where.And(e => e.CodEmpresa == codEmpresa);
where = where.And(e => e.nome.Contains(nome));

var lista = _db.Produtos.Where(where);

Você deve estar se perguntando, “nossa, mas tem mais código agora do que antes”. Sim, realmente ficou algumas linhas a mais, porém, devemos nos preocupar com a evolução de nossas aplicações e com a facilidade para manuteção/correção/implementação futuras. Deste ponto de vista, acredito que de uma forma geral acabamos ganhando em todos estes quesitos utilizando Predicated Builder para a criação de consultas deste tipo. Veja uma cenário mais complexo:

Vamos imaginar a consulta acima, considere que a mesma já foi criada da forma tradicional, e posteriomente o cliente pediu para incluirmos mais alguns campos para a consulta, vamos imaginar que foi solicitado: não trazer os produtos inativos, consulta por categoria, e por período de vencimento. Nossa querie ainda ficará pequena, porém, e a facilidade para manutenção, legibilidade, etc, etc, etc…?

Vamos implementar as solicitações acima com Predicated Builder:

int codEmpresa = 1;
string nome = "Caixa";
string nomeCategoria = "Recicláveis";
DateTime de = DateTime.Now.AddDays(-10);
DateTime ate = DateTime.Now.AddDays(10);

DB _db = new DB();

//Cláusula where
var where = PredicateBuilder.True<Produto>();

where = where.And(e => e.CodEmpresa == codEmpresa);
where = where.And(e => e.nome.Contains(nome));
where = where.And(e => !e.cancelada);
where = where.And(e => e.Categoria.nome.Contains(nomeCategoria));
where = where.And(e => de.Date <= e.dataVencimento.Date && ate.Date >= e.dataVencimento.Date);

var lista = _db.Produtos.Where(where);

Pronto, simples não?
Veja abaixo o código-fonte do Predicated Builder para você utiliza-lo em seus projetos também:

/// <summary>
/// Monta cláusula where dinamicamente
/// </summary>
public static class PredicateBuilder
{
    public static Expression<Func<T, bool>> True<T>()
    {
        return f => true;
    }

    public static Expression<Func<T, bool>> False<T>()
    {
        return f => false;
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                    Expression<Func<T, bool>> expr2)
    {
        InvocationExpression invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
            (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
    }

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                    Expression<Func<T, bool>> expr2)
    {
        InvocationExpression invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
            (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
    }
}

Veja no site do projeto outros exemplos e recursos:
http://www.albahari.com/nutshell/predicatebuilder.aspx

Bom por hoje era isso!
Abs.

 

Leave a Reply

Your email address will not be published. Required fields are marked *