Usuário com melhor resposta
Entity Framework - Inserção e Atualização com Many to Many

Pergunta
-
Pessoal boa noite tudo certo ?
Seguinte estou com duvidas de como devo persistir meus dados com o entity framework no banco de dados, eu tenho uma entidade Produtos que tem uma lista de promoções, é um N pra N biirecional, eu gostaria de cadastrar um produto já vinculando a ele promoções existentes na base de dados, porém fazendo desse jeito :
Produto produto = new Produto { nome = txtDescricao.Text, preco = Convert.ToDecimal(txtPreco.Text), apelido = this.txtCodigoCatalogo.Text, codigoMarca = ((Marca)this.cbxMarca.SelectedValue).codigo, codigoLinha = ((Linha)this.cbxLinha.SelectedValue).codigo, codigoTipo = ((Tipo)this.cbxTipo.SelectedValue).codigo, promocoes = this.promocaoParser.paraObjetos(this.lsbPromocoes) };
o entity framework esta inserindo o produto e as promoções, quando na verdade eu quero inserir o prouto e vincular ele a uma lista de produtos já cadastrados na base de dados e quando for realizar atualizações qual a forma que devo fazer ? Estou utilizando o entity framework 6 com sql server em um projeto de windows forms com C#
Obrigado
Respostas
-
Junior,
Não sei exatamente como está modelado seu banco de dados, mas leve em conta que no modelo relacional não existe o conceito de N:N.
Na prática, a solução para esta questão passa pela criação de uma entidade/tabela associativa. No caso, vc criaria algo como PromocaoProduto, ligando as entidades Produto e Promocao. Desta forma ficaria fácil transpor os dados para o seu banco.
Espero ter ajudado.
Abs- Sugerido como Resposta CarlosEduardo Ferreira quarta-feira, 10 de junho de 2015 12:47
- Marcado como Resposta Junior-kun segunda-feira, 15 de junho de 2015 17:28
Todas as Respostas
-
Junior,
Não sei exatamente como está modelado seu banco de dados, mas leve em conta que no modelo relacional não existe o conceito de N:N.
Na prática, a solução para esta questão passa pela criação de uma entidade/tabela associativa. No caso, vc criaria algo como PromocaoProduto, ligando as entidades Produto e Promocao. Desta forma ficaria fácil transpor os dados para o seu banco.
Espero ter ajudado.
Abs- Sugerido como Resposta CarlosEduardo Ferreira quarta-feira, 10 de junho de 2015 12:47
- Marcado como Resposta Junior-kun segunda-feira, 15 de junho de 2015 17:28
-
as entidades estão dessa forma :
[Table("produtos")] public class Produto { [Key] public Int64 codigo { get; set; } [Required] public string nome { get; set; } public decimal preco { get; set; } [Required] public string apelido { get; set; } public Int64 codigoTipo { get; set; } [ForeignKey("codigoTipo")] public virtual Tipo tipo {get; set;} public Int64 codigoLinha { get; set; } [ForeignKey("codigoLinha")] public virtual Linha linha { get; set; } public Int64 codigoMarca { get; set; } [ForeignKey("codigoMarca")] public virtual Marca marca { get; set; } public virtual IList<Promocao> promocoes { get; set; } }
[Table("promocoes")] public class Promocao { [Key] public Int64 codigo { get; set; } [Required] public string nome { get; set; } public float desconto { get; set; } [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")] public DateTime dataInicio { get; set; } [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")] public DateTime dataFim { get; set; } public virtual IList<Produto> produtos { get; set; } }
Então para eu conseguir criar um novo produto e associar uma lista de promoções a este mesmo produto eu vou ter que criar a entidade intermediaria para fazer isso na mão ? -
A solução o Renato Groffe já postou. Crie uma tabela associativa conforme te foi falado. Essa é a melhor forma que eu conheço para trata de relacionamentos N:N, se não for a única. O EF não vai entender como você gostaria. Ele não foi projetado para isso, pois feriria as regras de BD e etc. Desta forma você consegue associar um produto a uma ou mais promoções: Exemplo. Digamos que eu tenha o produto: PD1, PD2 e as promoções: PM1, PM2, PM3, PM4. Essas são as PK's. Na tabela associativa eu poderia ter:
PD1 >> PM1
PD1 >> PM2
PD1 >> PM4
PD2 >> PM1
PD2 >> PM3
E assim sucessivamente. Aí na sua LINQ você pegaria tudo que necessitasse e trabalharia com as informações já cadastradas. Isso foi o que o colega Renato Groffe disse. A resposta é dele, eu apenas exemplifiquei o que ele disse, nada mais.
-
Pessoal valeu a força ai e desculpa a demora, estou postado aqui o meu codigo de classe que recebe os Ids das outras classes, deu certo aqui, obrigado
public class ProdutoPromocao { [Column(Order = 0),Key] public Int64 coigoProduto { get; set; } [ForeignKey("coigoProduto")] public virtual Produto produto { get; set; } [Column(Order = 1), Key] public Int64 codigoPromocao { get; set; } [ForeignKey("codigoPromocao")] public virtual Promocao promocao { get; set; } }
-
Pessoal só para complementar a discussão com outras possíveis soluções do problema achei uma forma de mapear o relacionamento Many to Many sem a necessidade da criação da classe associativa somente com os objetos e códigos, mas tive que migrar para a fluent api, segue abaixo uma outra solução para o problema
Mapeamento da Classe produto:
public class ProdutoTypeConfiguration : EntityTypeConfiguration<Produto> { public ProdutoTypeConfiguration() { ToTable("PRODUTOS"); Property(p => p.Codigo) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) .IsRequired(); Property(p => p.Nome) .HasMaxLength(100) .IsRequired(); Property(p => p.Preco) .HasPrecision(8, 2) .IsRequired(); Property(p => p.Apelido) .HasMaxLength(20) .IsRequired(); HasKey(p => p.Codigo); HasRequired(p => p.Tipo) .WithMany(p => p.Produtos) .HasForeignKey(fk => fk.CodigoTipo) .WillCascadeOnDelete(false); HasRequired(p => p.Linha) .WithMany(p => p.Produtos) .HasForeignKey(fk => fk.CodigoLinha) .WillCascadeOnDelete(false); HasRequired(p => p.Marca) .WithMany(p => p.Produtos) .HasForeignKey(fk => fk.CodigoMarca) .WillCascadeOnDelete(false); HasMany(p => p.Promocoes) .WithMany(p => p.Produtos) .Map(m => { m.MapRightKey("codigo_produto"); m.MapLeftKey("codigo_promocao"); m.ToTable("produtos_promocoes"); }); } }
mapeamento da classe promoção:
public class PromocaoTypeConfiguration : EntityTypeConfiguration<Promocao> { public PromocaoTypeConfiguration() { ToTable("Promocoes"); Property(p => p.Codigo) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) .IsRequired(); Property(p => p.Nome) .HasMaxLength(100) .IsRequired(); Property(p => p.Desconto) .HasPrecision(8, 2) .IsRequired(); Property(p => p.DataInicio); Property(p => p.DataInicio); HasKey(p => p.Codigo); } }