none
Como inserir dados usando Entity Framework em relacionamentos N.N RRS feed

  • Pergunta

  • Olá galera, bom estou com uma dúvida no seguinte:

    Estou iniciando o uso do Entity Framework, segui essas video-aulas excelentes sobre desenvolvimento em N camadas com o Entity http://grou.ps/insidedotnet/videos do Andre Baltieri. Nele ele mostra tudo do CRUD basico, porem com somente uma entidade. Então criei um projeto e um banco de estudo com um relacionamento N para N entre a tabela Salarios e a Tabela Cargos.

    Eu cadastro primeiramente o cargo e depois posso cadastrar vários salarios para ele assim como vários salarios podem estar em um mesmo cargo (eu sei não é o melhor exemplo, mas é so pra treino mesmo).

    Com relacionamentos 1.1 ou 1.N consegui fazer sem maiores problemas. Porem nesse caso, toda a vez que eu vou inserir um salario ja selecionando o cargo do mesmo, ao invés dele cadastrar um novo registro criando uma nova entidade de salario e pegando a entidade de cargo que eu selecionei, ele cadastra novos dos dois. Ou Seja, eu seleciono um cargo, ele cria um novo cargo com os mesmos dados mais um codigo novo e associa ao salario novo e não é isso que eu quero, quero cadastrar um salario associado a um cargo ja cadastrado.

    como sugere o video separei minha aplicação em 3 Camadas (DAO, BO e View) o nome das classes são EntidadeBD para o DAO, EntidadeN para a camada de BO.

    Criei o modelo do entity apartir do Banco (Database First).

    Segue os codigos:

    Codigo da classe generica que tem todos os metodos crud genericos

    namespace EstudoEF.BD.Classes
    {
        public abstract class AbstractCrudBD<T>:IBaseBD<T> where T : class
        {
            Estudo2Entities banco = new Estudo2Entities();
    
            public void adicionar(T eEntidade)
            {
                banco.AddObject(eEntidade.GetType().Name, eEntidade);
            }
    
            public void alterar(T eEntidade)
            {
                banco.ApplyCurrentValues<T>(eEntidade.GetType().Name, eEntidade);
            }
    
            public void excluir(T eEntidade)
            {
                banco.DeleteObject(eEntidade);
            }
    
            public void anexar(T eEntidade)
            {
                banco.AttachTo(eEntidade.GetType().Name, eEntidade);
            }
    
            public void desmontar(T eEntidade)
            {
                banco.Detach(eEntidade);
            }
    
            public IQueryable<T> pesquisarCodigo(System.Linq.Expressions.Expression<Func<T, bool>> where)
            {
                return banco.CreateObjectSet<T>().Where(where);
            }
    
            public IQueryable<T> pesquisarTodos()
            {
                return banco.CreateObjectSet<T>();
    
            }
    
            public void saveChanges()
            {
                banco.SaveChanges();
               
            }
    
            public void dispose()
            {
                banco.Dispose();
            }
        }
    }

    Codigo da classe SalarioBD que tem o metodo de adicionarSalario puxando o cargo que eu quero associar:

        public class SalarioBD:AbstractCrudBD<Salario>, ISalario
        {
            Estudo2Entities banco = new Estudo2Entities();
            public IQueryable pesquisarPorCargo(System.Linq.Expressions.Expression<Func<Salario, bool>> where)
            {
                return banco.CreateObjectSet<Salario>().Where(where);
            }
    
    
            public void adicionarSalario(Salario s)
            {
                CargoBD cargoBD = new CargoBD();
                s.Cargos.Select(cargo => banco.Cargo.FirstOrDefault(r => r.Codigo == cargo.Codigo));
                banco.Salario.AddObject(s);
                banco.SaveChanges();
    
            }
        }

    Codigo da Pagina Web, do evento ao clicar no botão cadastrar salario

            protected void btnCadastrar_Click(object sender, EventArgs e)
            {
                SalarioN sN = new SalarioN();
                Salario s = new Salario();
                Cargo c = new Cargo();
                CargoN cN = new CargoN();
                int codigoCargo = Convert.ToInt32(ddlCargo.SelectedItem.Value);
                c = cN.pesquisarCodigo(r => r.Codigo == codigoCargo).First();
                cN.desmontar(c); //Detach
                cN.dispose();
                s.Valor = Convert.ToDecimal(txtValor.Text);
                s.Cargos.Add(c);
                sN.adicionarSalario(s);
                sN.saveChanges();
                CarregarSalarios();
    
            }

    alguém sabe onde estou errando? ja fazem algumas horas que estou travado nisso...

    Desde já agradeço 



    sexta-feira, 8 de fevereiro de 2013 15:08

Todas as Respostas

  • Verifique se a configuração do mapeamento do E.F esta dessa forma

        internal class SalarioMap : EntityTypeConfiguration<Salario>
        {
            public SalarioMap()
            {
               //Aqui você diz que 1 salario tem N Cargos
     HasMany(s => s.Cargos)
    //Aqui você diz que 1 Cargo tem N Salarios
                    .WithMany(c => c.Salarios)
                    .Map(f => 
    f.ToTable("NomeDaTabelaIntermediaria")
                                  .MapLeftKey("CargoId")
                                  .MapRightKey("SalarioId"));
    
    }}

    quinta-feira, 18 de abril de 2013 03:16
  • Parceiro se o mapeamento estiver correto é bem simples vamos la, nas configurações do seu projeto deixar a opcao lazy loading como true, essa opção serve para vc trazer dentro de uma entidade não apenas uma referencia a outra entidade relacionada mas todo o objeto, da uma estudada nisso que é bem legal, feito isso é bem simples o entity faz tudo sozinho da uma olhada no exemplo

             private void SalvarNota()
            {
                
                //Cria o objeto de nota
                Dados.Modelo.NotaFiscal nota = new Dados.Modelo.NotaFiscal();
                
                //Recupera dataset que possui os itens
                DataSet dsitens = (DataSet) ViewState["Vendas"];
    
                //Adiciona o cabeçalho da nota
                nota.Cliente_Codigo = Convert.ToInt32(ddlCliente.SelectedItem.Value) ;
                nota.Emissao_Nota = Convert.ToDateTime(data.Text);
                
                //Percorre os itens da nota
                int cont = 1;
                foreach(DataRow row in dsitens.Tables[0].Rows)
                {
                    ItensNota item = new ItensNota();
                    item.Seq_Item = cont;
                    item.Produto_Codigo = Convert.ToInt32(row["CODPRO"]);
                    item.Qtde_Item = Convert.ToInt32(row["QTDE"]);
                    item.Valor_Item = Convert.ToDouble(row["PRECO"].ToString().Replace("R$",""));
    
                    //Adiciona o item
                    nota.ItensNotas.Add(item);
                    cont += 1;
                
                }
    
                //Inclui a nota
                (new Negocio.NotasNegocio()).Incluir(nota);
    
                dsitens.Tables[0].Rows.Clear();
                ViewState["Vendas"] = dsitens;
                
            }

    No exemplo estou salvando uma Nota que tem a classe N:N para Itens de Nota. Primeiro crio a nota que só tem dois campos e não salvo no banco ainda. Pego os itens da nota que esta eu uma gridview onde os dados estao adicionados em um viewstate, ai eu percorro os itens da nota adicionando na mesma nota que foi criada anteriormente, ai eu insiro a nota com os itens normalmente. Obs o entity se encarrega do resto, tenta ai ve se vai funcionar

    Grato.



    • Editado thisderb sexta-feira, 19 de abril de 2013 10:33
    sexta-feira, 19 de abril de 2013 10:31