Baixe o app para aproveitar ainda mais
Prévia do material em texto
CENTRO UNIVERSITÁRIO DE PATOS DE MINAS EDUARDO HENRIQUE SILVA BUSINESS LOGIC LAYER (BLL) 1 1 INTRUDUÇÃO A camada BLL é responsável por implementar as regras de negócios da aplicação. Em várias regras de negócios é necessário a criação de consultas customizadas e parametrizadas, para a realização dessas consultas será utilizado LINQ e Expressões Lambda. 2 LINQ (LANGUAGE-INTEGRATED QUERY) E EXPRESSÕES LAMBDA O Entity Framework permite a interação com a base de dados, ou seja, toda a geração da linguagem de consulta é responsabilidade do framework. Os componentes LINQ e e as expressões Lambda, permitem a realização de consulta aos dados independente do fabricante do banco de dados, assim o desenvolvedor não precisa se preocupar com a escrita de SQL. As coleções que implementam a interface IEnumerable, tais como List, já estão preparadas para utilizar o LINQ e Expressões Lambda. O LINQ é uma linguagem tipada para consulta de dados, ou seja, ele utilizada as classes e atributos das entidades, tornando a consulta orientada a objetos. Exemplo: var etps = EtapaRepository.GetDbEntity(); var etapas = from etp in etps where etp.IdTipoEntrega == idTipoEntrega select etp; As expressões Lambda, permite a criação de consultas baseada em métodos, ou seja, podemos criar uma consulta por meio de várias chamadas de métodos. Exemplo: var etapas = etps.Where(x => x.IdTipoEntrega == idTipoEntrega); As principais vantagens desses modelos de consultas é a utilização de objetos, tornando a consulta tipada, a validação das consultas em tempo de compilação e a utilização do “IntelliSence” (auto-complete) na criação das consultas. As consultas não são executadas até que você acesse os resultados, isso é denominado “lazy evaluation”. É sempre importante utilizar o “ToList()” em suas consultas, 2 pois com esse comando sua consulta será executada imediatamente. Em consultas com o banco de dados, essa operação pode melhorar o desempenho. 2.1 EXEMPLOS Nessa seção serão apresentados alguns exemplos de consultas com LINQ e com Expressões Lambdas. Para os exemplos considere a seguinte fonte de dados (“etapas”) e as seguintes classes: var etapas = EtapaRepository.GetDbEntity(); public partial class Etapa { [Key] public int IdEtapa { get; set; } public int IdTipoEntrega { get; set; } public DateTime DataInicio { get; set; } public DateTime DataFim { get; set; } public decimal NotaMinima { get; set; } public virtual ICollection<Entrega> Entregas { get; set; } public virtual TipoEntrega TipoEntrega { get; set; } } public partial class TipoEntrega { [Key] public int IdTipoEntrega { get; set; } [Required] [StringLength(200)] public string Descricao { get; set; } } 3 public partial class Entrega { [Key] public int IdEntrega { get; set; } public int IdProjeto { get; set; } public int IdEtapa { get; set; } public DateTime Data { get; set; } public virtual Etapa Etapa { get; set; } } 2.1.1 Condição where Nas condições “where” é utilizada uma expressão booleana para avaliar quais dados serão retornados. Se o dado retornar verdadeiro ao avaliar a expressão, então esse dado é retornado na consulta. Ao criar uma consulta LINQ é necessário especificar um apelido (from), onde o apelido representa cada valor da fonte de dados, e a fonte de dados (in). E por fim informar quais dados serão selecionados (select). O código a seguir apresenta uma consulta com uma cláusula de restrição where, onde é selecionado apenas as etapas com o IdTipoEntrega igual a um. var resultado = (from etp in etapas where etp.IdTipoEntrega == 1 select etp).ToList(); A mesma consulta pode ser realizada utilizando uma expressão Lambda. As expressões Lambda são executadas por meio da invocação de métodos. Ao utilizar uma expressão Lambda você sempre terá o operador “=>”. Assim, é dividido em parte da esquerda (“parâmetros”) e parda da direita “bloco de instrução” (Parâmetros de entrada) => {Bloco de instrução}; Os parâmetros de entradas são tipos de dados implícitos ou explícitos a serem passados em um método. O bloco de instrução é similar ao código de um método que será executado. 4 O código a seguir apresenta uma expressão Lambda com o parâmetro de entrada “x” e realiza a soma de “x” + 1. Essa expressão pode ser chamada com: “incremento.Invoke(2)”, onde o seu resultado será igual a três. Func<int, int> incremento = (int x) => x + 1; As expressões Lambda podem serem utilizadas para extração de informações a partir de uma fonte de dados. Para isso alguns métodos foram disponibilizados, o código a seguir apresenta uma condição where utilizando uma expressão Lambda. var resultado = etapas.Where(x => x.IdTipoEntrega == 1).ToList(); Similar à linguagem SQL, podemos realizar uma série de comandos para realizar as restrições dos dados. Veja a tabela a seguir alguns exemplos: SQL LINQ e Lambda where NotaMinima > 10 OR NotaMinima < 0 x.NotaMinima > 10 | | x.NotaMinima < 0 where NotaMinima > 10 AND NotaMinima < 20 x.NotaMinima > 10 && x.NotaMinima < 20 where Descricao LIKE '%inicial%' x.Descricao.Contains(“inicial”) where Descricao LIKE 'inicial%' x.Descricao.StartsWith (“inicial”) where Descricao LIKE '%inicial' x.Descricao.EndsWith(“inicial”) where getdate() BETWEEN DataInicio and DataFim //Recupera a data atual DateTime dataAtual = DateTime.Now; x.DataInicio <= dataAtual && x.DataFim >= dataAtual where IdTipoEntrega IN (1,2,3) int[] códigos = new int[] {1,2,3}; codigos.Contains(x.IdTipoEntrega) 5 2.1.2 Ordenação A ordenação permite que um conjunto de dados seja classificado em crescente ou decrescente. No Linq a ordenação é realizada pela cláusula “orderby”. var resultado = (from etp in etapas orderby etp.IdTipoEntrega select etp).ToList(); Por padrão a classificação é realizada em ordem crescente (ascending). Ao realizar a ordenação é possível especificar se classificação é crescente (ascending) ou decrescente (descending). var resultado = (from etp in etapas orderby etp.IdTipoEntrega ascending select etp).ToList(); var resultado = (from etp in etapas orderby etp.IdTipoEntrega descending select etp).ToList(); Também é possível utilizar mais de um critério de ordenação. var resultado = (from etp in etapas orderby etp.DataInicio ascending, etp.DataFim descending select etp).ToList(); Para ordenação com expressões Lambda utilize os métodos OrderBy e OrderByDescending para ordenação crescente e decrescente respectivamente. var resultado = etapas.OrderBy(x => x.DataInicio).ToList(); var resultado = etapas.OrderByDescending(x => x.DataInicio).ToList(); 6 Para utilizar vários critérios de ordenação é necessário utilizar o método OrderBy ou OrderByDescending no primeiro critério de ordenação, nos critérios seguintes, utilize o método ThenBy ou ThenByDescending. var resultado = etapas.OrderBy(x => x.DataInicio) .ThenBy(x => x.DataFim).ThenByDescending(x=> x.IdEtapa).ToList(); 2.1.3 Joins A cláusula join só é necessário quando duas fontes de dados não estão ligadas por qualquer relação. Por exemplo, ao trabalhar com mapeamento objeto relacional a classe Etapa tem uma propriedade de TipoEtapa. Na verdade, a associação já foi feita para você ao realizar o relacionamento entre duas entidades. Considere duas fontes de dados “pessoas” e “usuarios” que não estão relacionadas, e é necessário recuperar todas as pessoas que possuem nomes iguais aos nomes de usuários. var resultados = from p in pessoas join u in usuarios on p.Nome equals u.NomeUsuario select p; A cláusula join realiza a junção em outra fonte de dados, assim é necessário comparar as chaves de igualdade, ou seja, os atributos que irão dizer quais nomes de pessoas são iguais aos nomes de usuários. Para a comparação utiliza-se o operador equals. Na expressão Lambda o join é utilizado o método Join. Esse método recebe quatro parâmetros: primeiramente a fonte de dados que será feito o join (“usuários”), em seguida a expressão que representa a chave de comparação da primeira fonte de dados (“p => p.Nome”), depois a expressão que representa a chave de comparação da segunda fonte de dados (“u => u.NomeUsuario”) e por fim qual ou quais objetos dados serão retornados (“(pessoa, usuario) => pessoa”). var resultados = pessoas.Join(usuarios, p => p.Nome, u => u.NomeUsuario, (pessoa, usuario) => pessoa); 7 Em fontes de dados que estão relacionadas, você pode fazer a navegação entre os objetos. Exemplo, no objeto “etp” referente as Etapas, podemos navegar nas propriedades do objeto e acessar o objeto “TipoEntrega”. var resultado = (from etp in etapas where etp.TipoEntrega.Descricao == "Inicial" select etp).ToList(); 2.1.4 Group by O agrupamento é utilizado quando deseja-se agrupar as informações dado um critério de agrupamento. Exemplo, o cliente solicitou um relatório que apresente as Etapas agrupado pelo TipoEntrega, conforme a Tabela a seguir. TipoEntrega Entrega Inicial Entrega 1 Entrega 2 Entrega 3 Final Entrega 5 Para realizar esse tipo de consulta é necessário realizar o agrupamento. No Linq para realizar o agrupamento é utilizado os operadores group, by e into. var resultado = (from etp in etapas group etp by etp.TipoEntrega into g select g).ToList(); A especificação dos critérios de agrupamento é especificada após a cláusula “by”, pode ser especificado um ou mais critérios de agrupamento. A cláusula “into” é utilizada para declarar uma variável que irá armazenar o resultado do agrupamento, para ser utilizada em uma cláusula where, order by ou select. 8 Para informar vários critérios de agrupamento utilize o operador new, e informe todos os critérios de agrupamento. var resultado = (from etp in etapas group etp by new { etp.TipoEntrega, etp.DataInicio } into g select g).ToList(); Ao realizar o agrupamento, o Linq retorna um IGrouping, um objeto que possui um atributo “Key” representado pelo critério de agrupamento e os “Elements” que são os objetos agrupados. Ao realizar a seleção de dados de saída no Linq é possível selecionar qual ou quais os atributos serão retornados. Na cláusula select utilize o operador new para selecionar o conjunto de atributos. var resultado = (from etp in etapas group etp by new { etp.TipoEntrega, etp.DataInicio } into g select new { TipoEntrega = g.Key.TipoEntrega.Descricao, Total = g.Count() }).ToList(); Ao utilizar o operador new conforme o exemplo acima é retornado um tipo anônimo. O tipo anônimo possui um conjunto de propriedades para somente leitura, e não há a necessidade de definir um tipo, o tipo é gerado pelo compilador e não está disponível a nível de código fonte, ou seja, esse tipo anônimo pode ser utilizado apenas no bloco que ele foi declarado. Se o resultado de sua consulta será retornado em um método ou manipulado no código fonte, você deverá criar uma classe “MinhaClasse” que possua os atributos necessários para armazenar o resultado de sua consulta. Assim, no operador new você pode especificar qual o tipo de objeto que será retornado na sua consulta. var resultado = (from etp in etapas group etp by new { etp.TipoEntrega, etp.DataInicio } into g select new MinhaClasse() { TipoEntrega = g.Key.TipoEntrega.Descricao, Total = g.Count() }).ToList(); 9 O agrupamento com Lambda é similar ao LINQ. Utilize o método Group para definir os critérios de agrupamento e o método Select para selecionar os dados de retorno da consulta. var resultado = etapas.GroupBy(x => new { x.TipoEntrega, x.DataInicio }) .Select(x => new MinhaClasse() { Descricao = x.Key.TipoEntrega, Total = x.Count() }); 2.1.5 Funções de agregação No desenvolvimento de software o agrupamento é realizado para agregar um conjunto de valores números. As funções de agregação permitem realizar o somatório (Sum), realizar a média (Average), recuperar o maior valor (Max), recuperar o menor valor (Min), realizar a contagem de elementos (Count). var resultado = (from etp in etapas group etp by new { etp.TipoEntrega, etp.DataInicio } into g select new { Contagem = g.Count(), Media = g.Average(x => x.NotaMinima), Maior = g.Max(x => x.IdEtapa), Menor = g.Min(x => x.IdEtapa), Somatorio = g.Sum(x => x.NotaMinima), }).ToList(); Esses métodos estão disponíveis em qualquer fonte de dados que implemente a interface IEnumerable, você pode utiliza-la em diversas situações, não é necessário sempre realizar o agrupamento. var resultado = (from etp in etapas select new { etp.TipoEntrega.Descricao, etp.Entregas.Count }).ToList(); 10 2.1.6 Distinct Para eliminar as informações duplicadas em uma consulta, utilize o método “Distinct”. var resultado = (from etp in etapas select new { etp.TipoEntrega.Descricao, }).Distinct().ToList(); 2.1.7 Take O método “Take” limita a quantidade de elementos que será retornada. No exemplo a seguir serão retornados 5 elementos. var resultado = (from etp in etapas select new { etp.TipoEntrega.Descricao, }).Take(5).ToList();
Compartilhar