Inquiridor
Persistir dados N:N usando entity

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:
CandidatoCompetencia (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
Todas as Respostas
-
-
-
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: