LINQ - Consultas Dinâmicas usando LINQ Dynamic Query Library


 No artigo de hoje veremos os conceitos básicos das consultas LINQ dinâmicas.

Dynamic LINQ API - Conceitos

Aplicações de banco de dados frequentemente dependem de consultas com "SQL dinâmico" que são construídas em tempo de execução através da lógica do programa.

A infraestrutura LINQ suporta capacidades semelhantes através da construção dinâmica de árvores de expressão, utilizando as classes no namespace System.Linq.Expressions.

Árvores de expressão são uma abstração adequada para uma variedade de cenários, mas para outros uma representação à base de strings pode ser mais conveniente.

A API LINQ Dynamic estende o núcleo da API LINQ com essa capacidade e depende de uma linguagem de expressão simples para a formulação de expressões e consultas em strings.

Você pode poder a API LINQ Dynamic neste link : https://dynamiclinq.codeplex.com/

A documentação completa pode ser vista aqui :  http://dynamiclinq.azurewebsites.net/

Lembrando que para poder usar os recursos da Dynamic LINQ você tem que usar o namespace System.Linq.Dynamic.

Apenas para você ter uma ideia do que essa API faz abaixo temos um exemplo de aplicação da API para uma fonte de dados LINQ to SQL:

var consulta = db.Customers
                     .Where(
"City = @0 and Orders.Count >= @1", "London", 10)
                     .OrderBy("CompanyName")
                     .Select("new(CompanyName as Name, Phone)");

 

Note como as cláusulas condicional Where e OrderBy agora usam uma expressão string ao invés de um expressão de código. Por causa da ligação tardia inerente a essas cláusulas podemos fazer isso.

A API Dynamic LINQ realiza o tratamento de erros usando a classe System.Linq.Dynamic.ParseException onde a propriedade Position da classe ParseException indica o índice do caractere na expressão string na qual o erro ocorreu.

 

A expressão de linguagem implementada na Dyanamic LINQ API fornece um maneira simples de escrever expressões que pode ser analisadas em árvores de expressões LINQ. A linguagem suporta muitos dos construtores das expression trees. (não há suporte para comandos e declarações.)

A Dynamic Expression API fornece os seguintes métodos de extensão IQueryable como parte da classe System.Linq.Dynamic.DynamicQueryable para consultar objetos de forma dinâmica:

public static IQueryable Where(this IQueryable source,  string predicate, params object[] values);
public static IQueryable<T> Where<T>(this IQueryable<T> source,   string predicate, params object[] values);
public static IQueryable Select(this IQueryable source,    string selector, params object[] values);
public static IQueryable OrderBy(this IQueryable source,    string ordering, params object[] values);
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,  string ordering, params object[] values);
public static IQueryable Take(this IQueryable source, int count);
public static IQueryable Skip(this IQueryable source, int count);
public static IQueryable GroupBy(this IQueryable source,    string keySelector, string elementSelector, params object[] values);
public static bool Any(this IQueryable source);
public static int Count(this IQueryable source);

Esses métodos operam em IQueryable e usam strings ao invés de expressões lambdas para expressar predicados, seletores e ordenações.

Recursos usados :

Exemplo prático no VS 2013 Express Edition

Abra o VS 2013 Express for Windows desktop e clique em New Project;

A seguir selecione Visual Basic -> Windows Forms Application;

Informe o nome LINQ_Consultas_Dinamicas e clique no botão OK;

A seguir vamos incluir a referência a API Dynamic LINQ usando o Nuget.

No menu TOOLS clique em Nuget Package Manager -> Manage Nuget Packages for Solution;

Na janela procure por LINQ Dynamic e instale o item referente ao System.Linq.Dynamic clique no botão Install;

Se preferir usar o Package Manager Console digite o seguinte comando no console :  Install-Package System.Linq.Dynamic

Agora já podemos usar o namespace System.Linq.Dynamic.

Vamos usar no projeto o LINQ to SQL para acessar o banco de dados Northwind.mdf e para isso vamos incluir uma referência ao LINQ to SQL classes no projeto.

Clique no menu PROJECT -> Add New Item e selecione LINQ to SQL Classes informando o nome Northwind.dbml e clique no botão Add;

A seguir vamos abrir a janela DataBase Explorer e selecionar a conexão com o banco de dados Northwind.mdf (se ela não existir você deve criar);

Selecione as tabelas Categories, Employees, Order Details, Orders e Products e arraste para o descritor LINQ to SQL para o gerar o arquivo Northwind.dbml contendo o mapeamento das classes para as tabelas do banco de dados;

Ao final teremos as classes mapeadas para as tabelas representadas conforme a figura abaixo:

No formulário form1.cs vamos incluir os seguintes controles a partir da ToolBox:

Disponha os controles no formulário conforme o leiaute da figura abaixo:

Agora vamos definir no formulário os namespaces usados no projeto:

using System;
using
System.Windows.Forms;
using
System.Linq.Dynamic;

A seguir no evento Click do botão de comando btnConsulta inclua o código abaixo:

   private void btnConsulta_Click(object sender, EventArgs e)
        {
            try
            {
                NorthwindDataContext db = new NorthwindDataContext();
               
                string condicao = "CategoryID=2 And UnitPrice>10";

                var produtos = db.Products
                                      .Where(condicao)
                                      .OrderBy("ProductName")
                                      .Select("new (ProductId, ProductName, UnitPrice, UnitsInStock)");
                dgvDados.DataSource = produtos;
            }
            catch(ParseException parex)
            {
                MessageBox.Show("Erro : " + pares.Position + parex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
   }

Note que definimos a variável condicao como sendo do tipo string e atribuímos a ela a condição que vamos usar na cláusula Where para filtrar os dados.

No código também usamos a classe ParseException para capturar erros de execução usando a propriedade Position para indicar a posição do caractere na expressão string onde o erro ocorreu.

Executando o projeto teremos o seguinte resultado gerado pela execução da consulta dinâmica LINQ:

A versão VB .NET do código é vista a seguir:

Private Sub btnConsulta_Click(sender As Object, e As EventArgs)
	Try
		Dim db As New NorthwindDataContext()
		Dim condicao As String = "CategoryID=2 And UnitPrice>10"
		Dim produtos = db.Products.Where(condicao).OrderBy("ProductName").Select("new (ProductId, ProductName, UnitPrice, UnitsInStock)")
		dgvDados.DataSource = produtos

	Catch parex As ParseException

		MessageBox.Show("Erro : " + pares.Position + parex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.[Error])
	End Try

End Sub

Pegue o projeto completo aqui:  LINQ_Consultas_DInamicas.zip

Todo aquele que prevarica, e não persevera na doutrina de Cristo, não tem a Deus. Quem persevera na doutrina de Cristo, esse tem tanto ao Pai como ao Filho.
2 João 1:9

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti