Como consultar (através do LINQ) e inserir registros (Entity Framework) em relacionamentos muitos para muitos (many to many)

Olá pessoal, tudo bom?

Supondo que você tenha o seguinte modelo de dados e deseje realizar consultas LINQ e também inserir registros via Entity Framework (EF).

Modelo:

Modelo de Dados
Clique na imagem para aumentar o zoom

Exemplo 1: Caso você queira recuperar as coleções relacionadas a um determinado item.

using (ColecionadorEntities contexto = new ColecionadorEntities())
{
   int codigoItem = 2; //Aqui vem o código do item que se deseja verificar
   /*Repare que se faz a chamada ao contexto buscando as classes Itens e Coleções
    *Para a classe Coleções, repare que a chamada é feita a partir do objeto i
    *pertencente à classe Itens */
   var dados = (from i in contexto.Itens
                from c in i.Colecoes
                where i.ite_codigo == codigoItem
                select new { c.clc_codigo, c.clc_nome }).ToList();

   for (int i = 0; i < dados.Count; i++)
   {
      Response.Write(dados[i].clc_codigo.ToString() + " - " + dados[i].clc_nome + "<br/>");
   }
}

Exemplo 2: Para inserir um novo item e já relaciona-lo às suas coleções

using (ColecionadorEntities contexto = new ColecionadorEntities())
{
   /*Em primeiro lugar, recupere os objetos da classe Coleções que serão associados
    *ao novo objeto da classe Itens. Nesse exemplo, estou considerando os objetos
    *c1 e c2 como sendo as coleções a serem relacionadas ao Item */
    int codigoColecao = 1;
    Colecoes c1 = PegaColecao(codigoColecao); //Suponha que o método pegaColecao devolva um objeto da classe Coleções
    codigoColecao = 2;
    Colecoes c2 = PegaColecao(codigoColecao);

    //Criando um novo objeto da classe Itens
    Itens it = new Itens();
    it.ite_nome = txtNome.Text;
    it.ite_descricao = txtDescricao.Text;
    it.ite_datacadastro = DateTime.Now;
    //Relacionando as coleções aos itens
    it.Colecoes.Add(c1);
    it.Colecoes.Add(c2);

    try
    {
       /*No momento em que se adiciona o objeto no contexto, os registros do relacionamento
        *muitos para muitos também são inseridos nas respectivas tabelas */
       contexto.Itens.AddObject(it);
       contexto.SaveChanges();
    }
    catch
    {
       Response.Write("Erro...");
    }
}

Grande abraço a todos!
Eduardo Henrique Rizo

[twitter-follow screen_name='eduardorizo' show_count='yes']

Post relacionado: Exemplo de inserção muitos para muitos usando EF5, Class Library, Linq e ASP.NET

6 comentários em “Como consultar (através do LINQ) e inserir registros (Entity Framework) em relacionamentos muitos para muitos (many to many)”

  1. Adicionar item para a coleção:
    int cod = int.Parse(ddlCol.SelectedValue);
    int coditem = int.Parse(ddlItem.SelectedValue);
    Colecoes c = (from x in contexto.Colecoes where x.clc_codigo == cod select x).First();
    Itens i = (from y in contexto.Itens where y.ite_codigo == coditem select y).First();
    c.Itens.Add(i); Adiciona o objeto do tipo Item dentro do Objeto coleção, ou seja , um item da coleção
    contexto.SaveChanges();
    lista(cod);
    ——————————————————————————————————————–
    Listar itens de uma determinada coleção:
    int cod = int.Parse(ddlCol.SelectedValue);
    var d = (from c in contexto.Colecoes
    where c.clc_codigo == cod
    select c).First();
    d.Itens.Load();
    var itens = d.Itens.Select(it => new { codigo = it.ite_codigo,nome = it.ite_nome });
    gvColItens.DataSource = itens;
    gvColItens.DataBind();
    ——————————————————————————————————————–
    Excluir item da coleção:

    int coditem = int.Parse(e.CommandArgument.ToString());
    int cod = int.Parse(ddlCol.SelectedValue);
    Colecoes c = (from x in contexto.Colecoes where x.clc_codigo == cod select x).First();
    Itens i = (from y in contexto.Itens where y.ite_codigo == coditem select y).First();
    c.Itens.Remove(i);
    contexto.SaveChanges();
    lista(cod);

  2. Pingback: LINQ, tipos anônimos e retorno de dados « Blog do Eduardo H. Rizo

  3. Pingback: Exemplo de inserção muitos para muitos usando EF5, Class Library, Linq e ASP.NET | Blog do Eduardo H. Rizo

  4. Olá Profº Eduardo, quando faço a inserção do muitos pra muitos utilizando a técnica que vc demonstra nesta publicação, além da inserir na tabela do muitos pra muitos ele duplica as coleções selecionadas, re-inserindo elas novamente na tabela de Coleções, porque isso acontece?

    1. Olá Bruno, tudo bom?

      O que ocorre é o seguinte: Repare que nesse os objetos da classe Colecoes foram criados dentro do mesmo contexto do objeto Itens, sendo assim, o EF já entende que eles fazem parte do mesmo contexto e que por isso não precisará inserir as coleções também.

      No caso do nosso exercício que foi proposto na aula, você deve estar passando um objeto Item com coleções dentro dele, porém essas coleções foram criadas em outros contexto, ou seja, para o EF elas não fazem parte do atual e por isso ele decide que precisarão ser inseridas novamente.

      O que se tem a fazer é realizar um Attach para cada objeto Colecao dentro de Item. Entendeu?

      Veja no link a seguir um exemplo de como realizar a mesma coisa que trabalhamos nesse post, mas agora usando o EF dentro de um Class Library e então tendo a necessidade de usar o Attach para resolver essa situação. Download aqui.

      Abraços,
      Prof. Eduardo

Deixe um comentário para André Luiz Carrilho de Aguiar Cancelar resposta