none
Insert em Relacionamento N para N - EF RRS feed

  • Pergunta

  • Pessoal,

    tenho uma tabela chamada PlanoAcao, uma tabela Acao e uma tabela PlanoAcao_Acao que mantém as ações que um plano de ação possui.

    No meu EDMX esta última tabela é excluída pelo EF.

    Desejo inserir um novo registro na tabela PlanoAcao, e adicionar registros na tabela PlanoAcao_Acao para manter as ações vinculadas ao novo plano.

    Os registros na tabela ação são pré-existentes.

    Quanto realizo o insert com o código abaixo, o EF está tentando inserir as ações selecionadas na tabela Acao, e há um erro pela violação da Unique Key.

    Como devo proceder?

    Os métodos 'Translate' apenas passam os dados dos DTO's para as entidades.

    privatebool Insert(PlanoAcaoDTO planoAcao, List<AcaoDTO> acoes)         {             bool ret = false;             EntityCollection<Acao> entityDetails = newEntityCollection<Acao>();             using (ErproAMEntities db = newErproAMEntities())             {                 foreach (AcaoDTO acao in acoes)                     entityDetails.Add(AcaoDAL.Translate(acao));                              PlanoAcao entityMaster = Translate(planoAcao);                 entityMaster.Acao = entityDetails;                                  db.PlanoAcao.AddObject(entityMaster);                 db.SaveChanges();

    ret = true;

                }             return ret;         }

       



    Alvimar A Silva

    sábado, 17 de março de 2012 19:22

Respostas

  • Olá Alvimar,

    Teste desta forma:

            private bool Insert(PlanoAcaoDTO planoAcao, List<AcaoDTO> acoes)
            {
                bool ret = false;
     
                EntityCollection<Acao> entityDetails = newEntityCollection<Acao>();
     
                using (ErproAMEntities db = newErproAMEntities())
                {
                    foreach (AcaoDTO acao in acoes)
    		{
    		    var acaoVar = AcaoDAL.Translate(acao);
                        entityDetails.Add(acaoVar);         
    		    db.NOME_DA_TABELA_DE_ACOES.Attach(acaoVar);    
    		    db.ObjectStateManager.ChangeObjectState(acao, System.Data.EntityState.Modified);
    		}
     
                    PlanoAcao entityMaster = Translate(planoAcao);
                    entityMaster.Acao = entityDetails;
                     
                    db.PlanoAcao.AddObject(entityMaster);
                    db.SaveChanges();                
    		ret = true;
                }
     
                return ret;
            }

    O direfente deste método é que estou utilizando o método Attach para conectar a instância com o seu contexto.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    • Marcado como Resposta Alvimar domingo, 18 de março de 2012 18:06
    domingo, 18 de março de 2012 16:32
    Moderador

Todas as Respostas

  •  Olá Alvimar,

    Talvez este código lhe ajude:

            privatebool Insert(PlanoAcaoDTO planoAcao, List<AcaoDTO> acoes)
            {
                bool ret = false;
     
                EntityCollection<Acao> entityDetails = newEntityCollection<Acao>();
     
                using (ErproAMEntities db = newErproAMEntities())
                {
                    foreach (AcaoDTO acao in acoes)
    		{
                        entityDetails.Add(AcaoDAL.Translate(acao));             
    		    db.ObjectStateManager.ChangeObjectState(acao, System.Data.EntityState.Modified);
    
    		}
     
                    PlanoAcao entityMaster = Translate(planoAcao);
                    entityMaster.Acao = entityDetails;
                     
                    db.PlanoAcao.AddObject(entityMaster);
                    db.SaveChanges();                ret = true;
                }
     
                return ret;
            }

    Utilize o ObjectStateManager para gerenciar o estado da instância do objeto com relação ao Entity Framework.

    Referência: http://msdn.microsoft.com/es-us/library/system.data.objects.objectstatemanager.aspx

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    domingo, 18 de março de 2012 04:23
    Moderador
  • Fernando,

    alterei na forma que você sugeriu, e foi disparada a seguinte exceção:

    The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'Prologica.ErproAM.Tipos.AcaoDTO'.

    Mudei então o código para testar assim

    db.ObjectStateManager.ChangeObjectState(AcaoDAL.Translate(acao), System.Data.EntityState.Modified);

    e obtive uma exceção do mesmo tipo:

    The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'Prologica.ErproAM.DAL.Acao'.

    Estou olhando a documentação mas ainda não consegui resolver...


    Alvimar A Silva

    domingo, 18 de março de 2012 15:51
  • Olá Alvimar,

    Teste desta forma:

            private bool Insert(PlanoAcaoDTO planoAcao, List<AcaoDTO> acoes)
            {
                bool ret = false;
     
                EntityCollection<Acao> entityDetails = newEntityCollection<Acao>();
     
                using (ErproAMEntities db = newErproAMEntities())
                {
                    foreach (AcaoDTO acao in acoes)
    		{
    		    var acaoVar = AcaoDAL.Translate(acao);
                        entityDetails.Add(acaoVar);         
    		    db.NOME_DA_TABELA_DE_ACOES.Attach(acaoVar);    
    		    db.ObjectStateManager.ChangeObjectState(acao, System.Data.EntityState.Modified);
    		}
     
                    PlanoAcao entityMaster = Translate(planoAcao);
                    entityMaster.Acao = entityDetails;
                     
                    db.PlanoAcao.AddObject(entityMaster);
                    db.SaveChanges();                
    		ret = true;
                }
     
                return ret;
            }

    O direfente deste método é que estou utilizando o método Attach para conectar a instância com o seu contexto.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    • Marcado como Resposta Alvimar domingo, 18 de março de 2012 18:06
    domingo, 18 de março de 2012 16:32
    Moderador
  • Fernando,

    funcionou, valeu a dica!!

    A única alteração foi na sua linha

    db.ObjectStateManager.ChangeObjectState(acao, System.Data.EntityState.Modified);

    onde é acaoVar no lugar de ação.

    Obrigado!


    Alvimar A Silva

    domingo, 18 de março de 2012 18:09
  • Alvimar,

    Tamo junto! :)

    O que precisar é soh falar!

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    segunda-feira, 19 de março de 2012 01:47
    Moderador