Melhor forma de fazer consulta usando linq

05/06/2015

Olá a todos,

Estou utilizando: Enity Framework Code First + Aplicação Windows Form + SGBD MySQL.

No meu formulário de consulta de fornecedor é possível filtrar por Razão, Fantasia e Cnpj. Bom a consulta está funcionando corretamente, pois tenho 3 métodos na minha camada DAL que conforme código abaixo:
public List<Fornecedor> FornecedorGetAllRazao(string FornecedorValueRazao, int EmpresaValueId)
        {
            try
            {
                using (var ctx = new Contexto())
                {
                    var consulta = from f in ctx.Fornecedores.ToList()
                                   where (f.Razao.Contains(FornecedorValueRazao) && f.Empresa_Id == EmpresaValueId)
                                   orderby f.Razao
                                   select f;

                    return consulta.ToList();
                }
            }
            catch (Exception ex)
            {                
                throw new Exception(ex.Message);
            }
        }

        public List<Fornecedor> FornecedorGetAllFantasia(string FornecedorValueFantasia, int EmpresaValueId)
        {
            try
            {
                using (var ctx = new Contexto())
                {                    
                    var consulta = from f in ctx.Fornecedores.ToList()
                                   where (f.Fantasia.Contains(FornecedorValueFantasia) && f.Empresa_Id == EmpresaValueId)
                                   orderby f.Razao
                                   select f;

                    return consulta.ToList();
                }
            }
            catch (Exception ex)
            {                
                throw new Exception(ex.Message);
            }
        }

        public List<Fornecedor> FornecedorGetAllCnpj(string FornecedorValueCnpj, int EmpresaValueId)
        {
            try
            {
                using (var ctx = new Contexto())
                {
                    var consulta = from f in ctx.Fornecedores.ToList()
                                   where (f.Cnpj.Contains(FornecedorValueCnpj) && f.Empresa_Id == EmpresaValueId)
                                   orderby f.Razao
                                   select f;

                    return consulta.ToList();
                }
            }
            catch (Exception ex)
            {                
                throw new Exception(ex.Message);
            }
        }


A minha duvida é: Se eu criar um método BuscarTodos() na minha camada DAL conforme o código abaixo:
 public List<Fornecedor> FornecedorGetAll(int EmpresaValueId)
        {
            try
            {
                using (var ctx = new Contexto())
                {
                    var consulta = from f in ctx.Fornecedores.ToList()
                                   where (f.Empresa_Id == EmpresaValueId)
                                   orderby f.Razao
                                   select f;

                    return consulta.ToList();
                }
            }
            catch (Exception ex)
            {                
                throw new Exception(ex.Message);
            }
        }


E se eu realizar o filtro da minha pesquisa em cima do método BuscarTodos() usando Lambda como no exemplo abaixo:
private void PesquisarFornecedor()
        {
            List<Fornecedor> lista = fornecedorBLL.FornecedorGetAll(EmpresaValueId);

            if (rbPorRazao.Checked == true)
            {
                lista = lista.Where(f => f.Razao.Contains(txtPesquisar.Text)).ToList();
                if (lista.Count == 0)
                {
                    MessageBox.Show("Nenhum registro encontrado", "SIGPRO - Aviso do Sistema", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    lbNumRegistroRetornados.Text = "0";
                    txtPesquisar.Text = "";
                    txtPesquisar.Focus();
                    dgvFornecedorPesquisar.DataSource = null;
                    return;
                }
                else if (lista.Count != 0)
                {
                    dgvFornecedorPesquisar.DataSource = lista;
                    int qtde = lista.Count();
                    lbNumRegistroRetornados.Text = qtde.ToString();
                }
            }
        }


Com isso poderia ter um ganho de performance e um menor consumo de recursos de rede eu daria na mesma?

Elessandro Poças

Respostas

11/06/2015

Joel Rodrigues Currículo

Olá, tudo bem?

Bom, isso não vai necessariamente lhe dar ganho de performance. Sobre tráfego de rede, vai ser na verdade maior, pois você estará trazendo todos os registros da tabela, ao invés de apenas os que você deseja.

Tire o ToList() da cláusula from das consultas, pois ela é desnecessária e gera uma lista com todos os registros, impactando no resultado final em termos de desempenho.

Abraço.
Responder Citar

12/06/2015

Elessandro Poças

Olá Joel,

Obrigado pela explicação.

Se eu tirar o ToList() das cláusula from a consulta não retorna nenhum dado. Quando eu usava a verão 4 do Entity Framework a mesma consulta funcionava perfeitamente após a versão 5 tive que usar o ToList() na cláusula from pois sem a mesma a consulta não retorna valores como mostrado na imagem em anexo.

[img:descricao=Teste Consulta Linq]http://arquivo.devmedia.com.br/forum/imagem/267760-20150612-090136.png[/img]

Agora não sei se estou fazendo algo de errado, se você puder me ajudar, deste já agradeço.
Responder Citar

12/06/2015

Joel Rodrigues Currículo

Olha lá em baixo: na variável consulta tem a instrução que está sendo executada, certo? Veja o conteúdo dela pra tentar entender por que não está retornando registro. Se precisar, cole aqui a instrução para analisarmos juntos.
Abraço.
Responder Citar

12/06/2015

Elessandro Poças

Joel, tô mais perdido que cego em tiroteio...

public List<Cliente> ClienteGetAllNomeRazao(string ClienteValueNomeRazao, int EmpresaValueId)
        {
            try
            {
                using (var ctx = new Contexto())
                {
                    var consulta = from c in ctx.Clientes
                                   where (c.ClienteNome.Contains(ClienteValueNomeRazao) && c.Empresa_Id == EmpresaValueId)
                                   orderby c.ClienteNome
                                   select c;

                    return consulta.ToList();
                }
            }
            catch (Exception ex)
            {                
                throw new Exception(ex.Message);
            }
        }
Responder Citar

12/06/2015

Joel Rodrigues Currículo

Ah, eu digo aí nessa imagem mesmo. Veja no canto inferior direito, quando o breakpoint é acionado, a janela "Locals". Uma das linhas é a variável consulta, que no lado direito tem seu valor equivalente em consulta SQL. Veja o conteúdo completo dessa instrução SQL para entender o porquê de não estar retornando registros.
Responder Citar

12/06/2015

Randrade

Alessandro, sobre ganho de desempenho, o Entity Framework peca um pouco. Vale ressaltar que melhorou muito, mas ainda sim é inferior que outros frameworks.

Eu estava tendo alguns problemas quando utilizava o entity. Porém, após algumas pesquisas, eu encontrei o Dapper. Em meus testes, triplicou a velocidade de minhas consultas. Porém, se quer performance mesmo, se cada milésimo importa, você terá que fazer isso via SQL puro mesmo, usando o SqlDataReader.

Segue uma tabela comparativa:
[img:descricao=Dapper vs Entity]http://arquivo.devmedia.com.br/forum/imagem/397347-20150612-105103.png[/img]

Esta tabela está desatualizada, o entity hoje está na faixa de 180ms.
Responder Citar

12/06/2015

Elessandro Poças

Joel,

Refiz a consulta da seguinte forma:

public List<Cliente> ClienteGetAllNomeRazao(string ClienteValueNomeRazao, int EmpresaValueId)
        {
            try
            {
                using (var ctx = new Contexto())
                {
                    var consulta = from c in ctx.Clientes.AsEnumerable().Where(c => c.ClienteNome.Contains(ClienteValueNomeRazao) && c.Empresa_Id == EmpresaValueId)                                   
                                   orderby c.ClienteNome
                                   select c;

                    return consulta.ToList();
                }
            }
            catch (Exception ex)
            {                
                throw new Exception(ex.Message);
            }
        }


Desta forma o from só buscou os dados que eu precisava, conforme imagem abaixo.
[img]http://arquivo.devmedia.com.br/forum/imagem/267760-20150612-140634.png[/img]
Responder Citar