none
Persistir dados N:N usando entity RRS feed

  • Pergunta

  • Olá pessoal, tudo bom?

    Criei um projeto teste para aprender a mexer com entity, até o momento estava tudo indo bem, agora emperrei ao tentar persistir em uma tabela associativa. Bom, é um projeto de cadastro de vaga de emprego, o cenário é esse:

    Tenho um domínio com  3 classes, são elas:
    Candidato

    Competencia (tecnologias que o candidato trabalha)

    VagaEmprego

    Na classe candidato eu tenho uma propriedade virtual ICollection do tipo competencia. Na classe competencia eu tenho uma propriedade virtual ICollection do tipo Candidato. Com essa estrutura eu consegui fazer com que o entity gerasse uma tabela associativa relacionando candidato e competencia em um relacionamento n:n.

    Na View de cadastro de candidatos eu carrego (usando ajax) uma lista com todas as competencias cadastradas previamente. O usuário informa os dados do candidado e seleciona suas competencias. No post os dados são enviados para o controller.

    O controller é uma WebApi, e lá eu recebo um objeto candidato, as informações chegam corretas (informações do candidato e lista de competencias selecionadas carregada na propriedade icollection). 

    PROBLEMA

    Quando executo o context.candidato.add(candidato); context.SaveChanges();

    Está inserindo o candidato (certo), mas, também está inserindo novamente as competencias (what?), e na tabela associativa ele está inserindo registros vinculando o candidato com as competencia que ele acabou de cadastrar, esse registro que ele está fazendo na tabela compentecia não deveria ser feito, umas vez que, eles já foram cadastrados previamente.

    Alguma ideia do que posso estar fazendo errado? Se precisar de mais detalhes, por favor, avisem.

    Obrigado

    quinta-feira, 14 de agosto de 2014 11:35

Todas as Respostas

  • Dani.ela,  poderia ver seu model em uma imagem fazendo favor? e a códificação mais ampla do seu código?

    Fulvio Cezar Canducci Dias

    quinta-feira, 14 de agosto de 2014 13:03
  • Dani.ela,  poderia ver seu model em uma imagem fazendo favor? e a códificação mais ampla do seu código?

    Fulvio Cezar Canducci Dias


    Veja se ajuda. Obrigado pelo retorno.
    • Editado dani.ela quinta-feira, 14 de agosto de 2014 13:26
    quinta-feira, 14 de agosto de 2014 13:25
  • Dani.ela, montei o mapeamento corretamente siga logo abaixo:

    public enum EstadoCivil
    {
    	Solteiro = 1,
    	Casado = 2,
    	Desquitado = 3,
    	Viúvo = 4
    }
    //Entidade Candidato
    public class Candidato
    {
    	public Candidato()
    	{
    		this.Competencia = new HashSet<Competencia>();
    	}
    	public int Id { get; set; }
    	public String Nome { get; set; }
    	public DateTime DataNascimento { get; set; }
    	public EstadoCivil EstadoCivil { get; set; }
    	public String Email { get; set; }
    	public String Telefone { get; set; }
    	public DateTime DataCadastro { get; set; }
    	public Boolean Ativo { get; set; }
    
    	public virtual ICollection<Competencia> Competencia { get; set; }
    }
    //Mapeamento Candidato
    public class CandidatoMap : EntityTypeConfiguration<Candidato>
    {
    	public CandidadoMap()
    	{
    		ToTable("Candidato");
    		HasKey(x => x.Id).Property(x => x.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    		Property(x => x.Nome).HasMaxLength(100).IsRequired();
    		Property(x => x.DataNascimento).IsRequired();
    		Property(x => x.EstadoCivil).IsRequired();
    		Property(x => x.Email).HasMaxLength(200).IsRequired();
    		Property(x => x.Telefone).HasMaxLength(14).IsRequired();
    		Property(x => x.DataCadastro).IsRequired();
    		Property(x => x.Ativo).IsRequired();
    		//N:M
    		HasMany(x => x.Competencia)
    			.WithMany(g => g.Candidato)
    			.Map(x =>  {
    				x.MapLeftKey("CandidatoId");
    				x.MapRightKey("CompetenciaId");
    				x.ToTable("CandidatoCompentencia");
    			}); 
    	}
    }
    //Entidade Competencia
    public class Competencia
    {
    	public Competencia()
    	{
    		this.Candidato = new HashSet<Candidato>();
    	}
    	public int Id { get; set; }
    	public String Nome { get; set; }
    	public virtual ICollection<Candidato> Candidato { get; set; }
    }
    //Mapeamento Competencia
    public class CompetenciaMap : EntityTypeConfiguration<Competencia>
    {
    	public CompetenciaMap()
    	{
    		ToTable("Competencia");
    		HasKey(x => x.Id).Property(x=>x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    		Property(x => x.Nome).HasMaxLength(100).IsRequired();
    	}
    }
    //DbContext
    public class Context : DbContext
    {
    	public Context()
    		:base("Data Source=.\\sqlexpress;Initial Catalog=DbSuper;Persist Security Info=True;User ID=sa;Password=senha;MultipleActiveResultSets=True;Application Name=EntityFramework") { }
    	protected override void OnModelCreating(DbModelBuilder modelBuilder)
    	{
    		modelBuilder.Configurations.Add<Candidato>(new CandidatoMap());
    		modelBuilder.Configurations.Add<Competencia>(new CompetenciaMap());
    		base.OnModelCreating(modelBuilder);
    	}
    	public DbSet<Competencia> Competencia { get; set; }
    	public DbSet<Candidato> Candidato { get; set; }
    }

    Para utilizar:

    Inserir registros:

    using (Context ctx = new Context())
    {
    	Candidato candidato1 = new Candidato();
    	candidato1.Ativo = true;
    	candidato1.DataCadastro = DateTime.Now;
    	candidato1.DataNascimento = DateTime.Parse("1/1/1991");
    	candidato1.Email = "email@teste1.com";
    	candidato1.EstadoCivil = EstadoCivil.Solteiro;
    	candidato1.Telefone = "(11)1111-1111";
    	candidato1.Nome = "Teste 1";
    
    	Candidato candidato2 = new Candidato();
    	candidato2.Ativo = false;
    	candidato2.DataCadastro = DateTime.Now;
    	candidato2.DataNascimento = DateTime.Parse("2/2/1992");
    	candidato2.Email = "email@teste2.com";
    	candidato2.EstadoCivil = EstadoCivil.Casado;
    	candidato2.Telefone = "(22)2222-2222";
    	candidato2.Nome = "Teste 2";
    
    
    	Competencia competencia1 = new Competencia();
    	competencia1.Nome = "Auxiliar Administrativo";
    
    	//INSERÇÕES COMUNS;
    	ctx.Candidato.Add(candidato1);
    	ctx.Candidato.Add(candidato2);
    	ctx.Competencia.Add(competencia1);
    	ctx.SaveChanges();
    
    	//INSERÇÕES NA TABELA INTERMEDIÁRIA (N:M) CandidatoCompetencia
    	candidato1.Competencia.Add(competencia1);
    	candidato2.Competencia.Add(competencia1);
    	ctx.SaveChanges();
    	
    }

    Select Registros:

    using (Context ctx = new Context())
    {
    	Competencia competencia = ctx.Competencia.Find(1);                
    }

    Aonde essa competencia possui dois candidatos na tabela de muitos para muitos.

    Layout base de dados:


    Fulvio Cezar Canducci Dias

    quinta-feira, 14 de agosto de 2014 14:28