Início > LINQ > LINQ: IN no Entity Framework

LINQ: IN no Entity Framework

Uma das muitas dúvidas sobre o Entity Framework é como fazer um IN. Muitos exemplos na Internet explicam que devemos utilizar o Contains e isso é verdade. O problema é que Contains não funciona quando fazemos LINQ com acesso a banco de dados no Entity Framework.

Veja um exemplo de LINQ to Entity utilizando o banco de dados AdventureWorks.

List<int> ids = new List<int>(){1, 2};

var varEmployee = from em in ef.Employee
               where ids.Contains(em.EmployeeID)
               select new
               {
                 ID = em.EmployeeID,
                 BirthDate = em.BirthDate
               };

GridView1.DataSource = varEmployee;
GridView1.DataBind();

Fazendo dessa forma teremos uma mensagem de erro:

LINQ to Entities não reconhece o método ‘Boolean Contains(Int32)’, que não pode ser convertido em uma expressão de armazenamento.

Isso acontece porque o Entity Framework ao converter o LINQ para T-SQL, não compreende o Contains.

Temos uma forma de resolver isso, fazendo como o exemplo abaixo:

List<int> ids = new List<int>(){1, 2};

var varEmployee = from em in ef.Employee.AsEnumerable()
               where ids.Contains(em.EmployeeID)
               select new
               {
                 ID = em.EmployeeID,
                 BirthDate = em.BirthDate
               };

GridView1.DataSource = varEmployee;
GridView1.DataBind();

Podemos substituir o AsEnumerable por ToList, teremos o mesmo resultado. Dessa forma o IN será realizado.

Cuidado: Quando você realiza o AsEnumerable ou ToList() ele tráz tudo do banco, perdendo a funcionalidade de filtrar antes do acesso. Mas em outras ocasiões como em uma lista muito grande que você utilizará no contains, você tem certas vantagens.

Gostaria de agradecer a Murilo Amaru Gomes que me ajudou a compreender essa funcionalidade do LINQ.

Obrigado pessoal e até a próxima.

Anúncios
Categorias:LINQ Tags:, ,
  1. agosto 20, 2010 às 10:29 am

    Olá,
    O Contains pode até funcionar quando temos uma lista que NÃO venha de uma entidade do modelo.
    Se ids fosse uma lista do tipo List, exemplo:
    exemplo:
    List qry = (from u in dm.entidade
    where ….
    select new entidade_modelo {id = u.id}).ToList();

    O Contains não funcionaria. Já fiz o teste e quebrei muito a cabeça por isso.

    • agosto 20, 2010 às 12:11 pm

      Olá Mauricio, você tentou onde está

      from u in dm. entidade
      
      // para
      
      from u in dm.entidade.ToList()
      
  2. agosto 20, 2010 às 10:30 am

    O Contains funcionaria apenas com o Linq To SQL…mas nao com o Entity Data Model.

    • agosto 20, 2010 às 12:12 pm

      Olá no exemplo do artigo irá funcionar com Entity Framework. Meu exemplo foi feito nele.

      Obrigado.

  3. agosto 26, 2010 às 3:33 pm

    Olá amigo, ja tentei sim, mas não deu certo :S
    O que eu consegui, foi arrumar um jeito brasileiro, que esta no meu blog.

    • agosto 26, 2010 às 5:24 pm

      Estranho porque utilizamos aqui e funciona. Uma pergunta você está usando EF com framework 3.5 ou 4.0?

  4. agosto 30, 2010 às 5:15 pm

    Utilizo o 3.5
    Talvez no 4.0 devem ter arrumado.

  5. agosto 30, 2010 às 5:18 pm

    Só para você ter uma ideia:
    List listaColetas = (from i in dm.vw_ve_itenscoleta
    where i.idcliente == idcliente
    && i.status_coleta == “PROCESSADA”
    && i.DATA >= datade && i.DATA <= dataate
    select i.idmontadora).ToList();

    var qryMontadoras = from m in dm.ve_montadoras
    where listaColetas.Contains(m.idmontadora)
    select m;

    Na hora que vou iniciar o foreach, ele me gera o seguinte erro:

    LINQ to Entities does not recognize the method 'Boolean Contains(Int64)' method, and this method cannot be translated into a store expression.
    o Campo idmontadora é do tipo Int64.

  6. agosto 30, 2010 às 6:20 pm

    Ah amigo, faltou o .AsEnumerable()
    eu acrescentei isso na minha segunda query e deu certo…vlw..obrigado.

  7. fevereiro 20, 2011 às 9:43 pm

    Valeu, resolveu meus problemas!!

  8. março 14, 2011 às 5:26 pm

    Olá amigo, eu estou com outra query e estou tendo problemas ao acionar o método AsEnumerable().
    Esta me voltando o seguinte erro:
    Unable to convert MySQL date/time value to System.DateTime

    O que pode estar havendo?
    Eu utilizando Entity e consigo visualizar os registros normalmente quando não faço o Contains…

  9. Leonardo Lima
    abril 19, 2011 às 2:10 pm

    Olá, Tive o mesmo problema e detectei que estava relacionado a letras maiusculas e minusculas. O Contais faz a destinção de caixa alta e caixa baixo como no SQL. Segue a solução sem precisar converter para AsEnumerable ou ToList().

    01 List ids = new List(){1, 2};
    02
    03 var varEmployee = from em in ef.Employee.AsEnumerable()
    04 where ids.ToUpper().Contains(em.EmployeeID.ToUpper())
    05 select new
    06 {
    07 ID = em.EmployeeID,
    08 BirthDate = em.BirthDate
    09 };
    10
    11 GridView1.DataSource = varEmployee;
    12 GridView1.DataBind();

    Notem que fiz o cast “ToUpper()” nos dois lados da consulta.
    Espero ter ajudado.

  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: